/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: sw=2 ts=8 et :
*/ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// How long we wait for data from glxtest/vaapi test process in milliseconds. #define GFX_TEST_TIMEOUT 4000 #define VAAPI_TEST_TIMEOUT 2000 #define V4L2_TEST_TIMEOUT 2000
int GfxInfo::sGLXTestPipe = -1;
pid_t GfxInfo::sGLXTestPID = 0;
// bits to use decoding codec information returned from glxtest
constexpr int CODEC_HW_H264 = 1 << 4;
constexpr int CODEC_HW_VP8 = 1 << 5;
constexpr int CODEC_HW_VP9 = 1 << 6;
constexpr int CODEC_HW_AV1 = 1 << 7;
GUniquePtr<GError> error;
gsize length = 0; int ret; do {
error = nullptr;
ret = g_io_channel_read_to_end(channel, aData, &length,
getter_Transfers(error));
} while (ret == G_IO_STATUS_AGAIN && TimeStamp::Now() < deadline); if (error || ret != G_IO_STATUS_NORMAL) {
gfxCriticalNote << "ManageChildProcess(" << aProcessName
<< "): failed to read data from child process: "; if (error) {
gfxCriticalNote << error->message;
} else {
gfxCriticalNote << "timeout";
} returnfalse;
}
int status = 0; int pid = *aPID;
*aPID = -1;
while (true) { int ret = waitpid(pid, &status, WNOHANG); if (ret > 0) { break;
} if (ret < 0) { if (errno == ECHILD) { // Bug 718629 // ECHILD happens when the glxtest process got reaped got reaped after a // PR_CreateProcess as per bug 227246. This shouldn't matter, as we // still seem to get the data from the pipe, and if we didn't, the // outcome would be to blocklist anyway. returntrue;
} if (errno != EAGAIN && errno != EINTR) {
gfxCriticalNote << "ManageChildProcess(" << aProcessName
<< "): waitpid failed: " << strerror(errno) << "\n"; returnfalse;
}
} if (TimeStamp::Now() > deadline) {
gfxCriticalNote << "ManageChildProcess(" << aProcessName
<< "): process hangs\n"; returnfalse;
} // Wait 50ms to another waitpid() check.
usleep(50000);
}
// to understand this function, see bug 639842. We retrieve the OpenGL driver // information in a separate process to protect against bad drivers. void GfxInfo::GetData() { if (mInitialized) { return;
}
mInitialized = true;
// In some cases (xpcshell test, Profile manager etc.) // FireGLXTestProcess() is not fired in advance // so we call it here.
GfxInfo::FireGLXTestProcess();
// Available if GLX_MESA_query_renderer is supported.
nsCString mesaVendor;
nsCString mesaDevice;
nsCString mesaAccelerated; // Available if using a DRI-based libGL stack.
nsCString driDriver;
nsCString adapterRam;
if (!strcmp(textureFromPixmap.get(), "TRUE")) mHasTextureFromPixmap = true;
// only useful for Linux kernel version check for FGLRX driver. // assumes X client == X server, which is sad. struct utsname unameobj{}; if (uname(&unameobj) >= 0) {
mOS.Assign(unameobj.sysname);
mOSRelease.Assign(unameobj.release);
}
constchar* spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR"); if (spoofedVendor) glVendor.Assign(spoofedVendor); constchar* spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER"); if (spoofedRenderer) glRenderer.Assign(spoofedRenderer); constchar* spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION"); if (spoofedVersion) glVersion.Assign(spoofedVersion); constchar* spoofedOS = PR_GetEnv("MOZ_GFX_SPOOF_OS"); if (spoofedOS) mOS.Assign(spoofedOS); constchar* spoofedOSRelease = PR_GetEnv("MOZ_GFX_SPOOF_OS_RELEASE"); if (spoofedOSRelease) mOSRelease.Assign(spoofedOSRelease);
// Scan the GL_VERSION string for the GL and driver versions.
nsCWhitespaceTokenizer tokenizer(glVersion); while (tokenizer.hasMoreTokens()) {
nsCString token(tokenizer.nextToken()); unsignedint major = 0, minor = 0, revision = 0, patch = 0; if (sscanf(token.get(), "%u.%u.%u.%u", &major, &minor, &revision, &patch) >=
2) { // A survey of GL_VENDOR strings indicates that the first version is // always the GL version, the second is usually the driver version. if (mGLMajorVersion == 0) {
mGLMajorVersion = major;
mGLMinorVersion = minor;
} elseif (mDriverVersion.IsEmpty()) { // Not already spoofed.
mDriverVersion =
nsPrintfCString("%u.%u.%u.%u", major, minor, revision, patch);
}
}
}
if (mGLMajorVersion == 0) {
NS_WARNING("Failed to parse GL version!");
}
// Mesa always exposes itself in the GL_VERSION string, but not always the // GL_VENDOR string.
mIsMesa = glVersion.Find("Mesa") != -1;
// We need to use custom driver vendor IDs for mesa so we can treat them // differently than the proprietary drivers. if (mIsMesa) {
mIsAccelerated = !mesaAccelerated.Equals("FALSE"); // Process software rasterizers before the DRI driver string; we may be // forcing software rasterization on a DRI-accelerated X server by using // LIBGL_ALWAYS_SOFTWARE or a similar restriction. if (strcasestr(glRenderer.get(), "llvmpipe")) {
CopyUTF16toUTF8(
GfxDriverInfo::GetDriverVendor(DriverVendor::MesaLLVMPipe),
mDriverVendor);
mIsAccelerated = false;
} elseif (strcasestr(glRenderer.get(), "softpipe")) {
CopyUTF16toUTF8(
GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSoftPipe),
mDriverVendor);
mIsAccelerated = false;
} elseif (strcasestr(glRenderer.get(), "software rasterizer")) {
CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSWRast),
mDriverVendor);
mIsAccelerated = false;
} elseif (strcasestr(driDriver.get(), "vmwgfx")) {
CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaVM),
mDriverVendor);
mIsAccelerated = false;
} elseif (!mIsAccelerated) {
CopyUTF16toUTF8(
GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSWUnknown),
mDriverVendor);
} elseif (!driDriver.IsEmpty()) {
mDriverVendor = nsPrintfCString("mesa/%s", driDriver.get());
} else { // Some other mesa configuration where we couldn't get enough info.
NS_WARNING("Failed to detect Mesa driver being used!");
CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaUnknown),
mDriverVendor);
}
if (!mesaVendor.IsEmpty()) {
mVendorId = mesaVendor;
}
if (!mesaDevice.IsEmpty()) {
mDeviceId = mesaDevice;
}
if (!mIsAccelerated && mVendorId.IsEmpty()) {
mVendorId.Assign(glVendor.get());
}
if (!mIsAccelerated && mDeviceId.IsEmpty()) {
mDeviceId.Assign(glRenderer.get());
}
} elseif (glVendor.EqualsLiteral("NVIDIA Corporation")) {
CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
mVendorId);
mDriverVendor.AssignLiteral("nvidia/unknown"); // TODO: Use NV-CONTROL X11 extension to query Device ID and VRAM.
} elseif (glVendor.EqualsLiteral("ATI Technologies Inc.")) {
CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
mVendorId);
mDriverVendor.AssignLiteral("ati/unknown"); // TODO: Look into ways to find the device ID on FGLRX.
} else {
NS_WARNING("Failed to detect GL vendor!");
}
if (!adapterRam.IsEmpty()) {
mAdapterRAM = (uint32_t)atoi(adapterRam.get());
}
// If we have the DRI driver, we can derive the vendor ID from that if needed. if (mVendorId.IsEmpty() && !driDriver.IsEmpty()) { constchar* nvidiaDrivers[] = {"nouveau", "tegra", nullptr}; for (size_t i = 0; nvidiaDrivers[i]; ++i) { if (driDriver.Equals(nvidiaDrivers[i])) {
CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
mVendorId); break;
}
}
if (mVendorId.IsEmpty()) { constchar* intelDrivers[] = {"iris", "crocus", "i915", "i965", "i810", "intel", nullptr}; for (size_t i = 0; intelDrivers[i]; ++i) { if (driDriver.Equals(intelDrivers[i])) {
CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::Intel),
mVendorId); break;
}
}
}
if (mVendorId.IsEmpty()) { constchar* amdDrivers[] = {"r600", "r200", "r100", "radeon", "radeonsi", nullptr}; for (size_t i = 0; amdDrivers[i]; ++i) { if (driDriver.Equals(amdDrivers[i])) {
CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
mVendorId); break;
}
}
}
if (mVendorId.IsEmpty()) { if (driDriver.EqualsLiteral("freedreno")) {
CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::Qualcomm),
mVendorId);
}
}
}
// If we still don't have a vendor ID, we can try the PCI vendor list. if (mVendorId.IsEmpty()) { if (pciVendors.IsEmpty()) {
gfxCriticalNote << "No GPUs detected via PCI\n";
} else { for (size_t i = 0; i < pciVendors.Length(); ++i) { if (mVendorId.IsEmpty()) {
mVendorId = pciVendors[i];
} elseif (mVendorId != pciVendors[i]) {
gfxCriticalNote << "More than 1 GPU vendor detected via PCI, cannot " "deduce vendor\n";
mVendorId.Truncate(); break;
}
}
}
}
// If we know the vendor ID, but didn't get a device ID, we can guess from the // PCI device list. if (mDeviceId.IsEmpty() && !mVendorId.IsEmpty()) { for (size_t i = 0; i < pciLen; ++i) { if (mVendorId.Equals(pciVendors[i])) { if (mDeviceId.IsEmpty()) {
mDeviceId = pciDevices[i];
} elseif (mDeviceId != pciDevices[i]) {
gfxCriticalNote << "More than 1 GPU from same vendor detected via " "PCI, cannot deduce device\n";
mDeviceId.Truncate(); break;
}
}
}
}
// Assuming we know the vendor, we should check for a secondary card. if (!mVendorId.IsEmpty()) { if (pciLen > 2) {
gfxCriticalNote
<< "More than 2 GPUs detected via PCI, secondary GPU is arbitrary\n";
} for (size_t i = 0; i < pciLen; ++i) { if (!mVendorId.Equals(pciVendors[i]) ||
(!mDeviceId.IsEmpty() && !mDeviceId.Equals(pciDevices[i]))) {
mSecondaryVendorId = pciVendors[i];
mSecondaryDeviceId = pciDevices[i]; break;
}
}
}
// If we couldn't choose, log them. if (mVendorId.IsEmpty()) { for (size_t i = 0; i < pciLen; ++i) {
gfxCriticalNote << "PCI candidate " << pciVendors[i].get() << "/"
<< pciDevices[i].get() << "\n";
}
}
// Fallback to GL_VENDOR and GL_RENDERER. if (mVendorId.IsEmpty()) {
mVendorId.Assign(glVendor.get());
} if (mDeviceId.IsEmpty()) {
mDeviceId.Assign(glRenderer.get());
}
mAdapterDescription.Assign(glRenderer);
// Make a best effort guess at whether or not we are using the XWayland compat // layer. For all intents and purposes, we should otherwise believe we are // using X11.
mIsWayland = GdkIsWaylandDisplay();
mIsXWayland = IsXWaylandProtocol();
if (!ddxDriver.IsEmpty()) {
PRInt32 start = 0;
PRInt32 loc = ddxDriver.Find(";", start); while (loc != kNotFound) {
nsCString line(ddxDriver.get() + start, loc - start);
mDdxDrivers.AppendElement(std::move(line));
start = loc + 1;
loc = ddxDriver.Find(";", start);
}
}
if (error || errorLog || mTestType.IsEmpty()) { if (!mAdapterDescription.IsEmpty()) {
mAdapterDescription.AppendLiteral(" (See failure log)");
} else {
mAdapterDescription.AppendLiteral("See failure log");
}
char* bufptr = vaapiData; char* line; while ((line = NS_strtok("\n", &bufptr))) { if (!strcmp(line, "VAAPI_SUPPORTED")) {
line = NS_strtok("\n", &bufptr); if (!line) {
gfxCriticalNote << "vaapitest: Failed to get VAAPI support\n"; return;
}
mIsVAAPISupported = Some(!strcmp(line, "TRUE"));
} elseif (!strcmp(line, "VAAPI_HWCODECS")) {
line = NS_strtok("\n", &bufptr); if (!line) {
gfxCriticalNote << "vaapitest: Failed to get VAAPI codecs\n"; return;
}
std::istringstream(line) >> mVAAPISupportedCodecs; if (mVAAPISupportedCodecs & CODEC_HW_H264) {
media::MCSInfo::AddSupport(
media::MediaCodecsSupport::H264HardwareDecode);
} if (mVAAPISupportedCodecs & CODEC_HW_VP8) {
media::MCSInfo::AddSupport(
media::MediaCodecsSupport::VP8HardwareDecode);
} if (mVAAPISupportedCodecs & CODEC_HW_VP9) {
media::MCSInfo::AddSupport(
media::MediaCodecsSupport::VP9HardwareDecode);
} if (mVAAPISupportedCodecs & CODEC_HW_AV1) {
media::MCSInfo::AddSupport(
media::MediaCodecsSupport::AV1HardwareDecode);
}
} elseif (!strcmp(line, "WARNING") || !strcmp(line, "ERROR")) {
gfxCriticalNote << "vaapitest: " << line;
line = NS_strtok("\n", &bufptr); if (line) {
gfxCriticalNote << "vaapitest: " << line << "\n";
} return;
}
} #endif
}
// Probe all V4L2 devices and check their capabilities void GfxInfo::GetDataV4L2() { if (mIsV4L2Supported.isSome()) { // We have already probed v4l2 support, no need to do it again. return;
}
mIsV4L2Supported = Some(false);
#ifdef MOZ_ENABLE_V4L2
DIR* dir = opendir("/dev"); if (!dir) {
gfxCriticalNote << "Could not list /dev\n"; return;
} struct dirent* dir_entry; while ((dir_entry = readdir(dir))) { if (!strncmp(dir_entry->d_name, "video", 5)) {
nsCString path = "/dev/"_ns;
path += nsDependentCString(dir_entry->d_name);
V4L2ProbeDevice(path);
}
}
closedir(dir); #endif// MOZ_ENABLE_V4L2
}
// Check the capabilities of a single V4L2 device. If the device doesn't work // or doesn't support any codecs we recognise, then we just ignore it. If it // does support recognised codecs then add these codecs to the supported list // and mark V4L2 as supported: We only need a single working device to enable // V4L2, when we come to decode FFmpeg will probe all the devices and choose // the appropriate one. void GfxInfo::V4L2ProbeDevice(nsCString& dev) { char* v4l2Data = nullptr; auto free = mozilla::MakeScopeExit([&] { g_free((void*)v4l2Data); });
int v4l2Pipe = -1; int v4l2PID = 0; constchar* args[] = {"-d", dev.get(), nullptr};
v4l2PID = FireTestProcess(V4L2_PROBE_BINARY, &v4l2Pipe, args); if (!v4l2PID) {
gfxCriticalNote << "Failed to start v4l2test process\n"; return;
}
char* bufptr = v4l2Data; char* line;
nsTArray<nsCString> capFormats;
nsTArray<nsCString> outFormats; bool supported = false; // Use gfxWarning rather than gfxCriticalNote from here on because the // errors/warnings output by v4l2test are generally just caused by devices // which aren't M2M decoders. Set gfx.logging.level=5 to see these messages.
while ((line = NS_strtok("\n", &bufptr))) { if (!strcmp(line, "V4L2_SUPPORTED")) {
line = NS_strtok("\n", &bufptr); if (!line) {
gfxWarning() << "v4l2test: Failed to get V4L2 support\n"; return;
}
supported = !strcmp(line, "TRUE");
} elseif (!strcmp(line, "V4L2_CAPTURE_FMTS")) {
line = NS_strtok("\n", &bufptr); if (!line) {
gfxWarning() << "v4l2test: Failed to get V4L2 CAPTURE formats\n"; return;
} char* capture_fmt; while ((capture_fmt = NS_strtok(" ", &line))) {
capFormats.AppendElement(capture_fmt);
}
} elseif (!strcmp(line, "V4L2_OUTPUT_FMTS")) {
line = NS_strtok("\n", &bufptr); if (!line) {
gfxWarning() << "v4l2test: Failed to get V4L2 OUTPUT formats\n"; return;
} char* output_fmt; while ((output_fmt = NS_strtok(" ", &line))) {
outFormats.AppendElement(output_fmt);
}
} elseif (!strcmp(line, "WARNING") || !strcmp(line, "ERROR")) {
line = NS_strtok("\n", &bufptr); if (line) {
gfxWarning() << "v4l2test: " << line << "\n";
} return;
}
}
// If overall SUPPORTED flag is not TRUE then stop now if (!supported) { return;
}
// Currently the V4L2 decode platform only supports YUV420 and NV12 if (!capFormats.Contains("YV12") && !capFormats.Contains("NV12")) { return;
}
// Disable on all older Nvidia drivers due to stability issues.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::NonMesaAll, DeviceFamily::NvidiaAll,
nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_LESS_THAN, V(470, 82, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_NVIDIA", "470.82.0");
// Older generation NVIDIA devices do not perform well with WebRender.
APPEND_TO_DRIVER_BLOCKLIST(
OperatingSystem::Linux, DeviceFamily::NvidiaWebRenderBlocked,
nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "NVIDIA_EARLY_TESLA_AND_C67_C68", "");
// Mesa baseline, chosen arbitrarily. Linux users are generally good about // updating their Mesa libraries so we don't want to arbitarily support // WebRender on old drivers with outstanding bugs to work around.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::MesaAll, DeviceFamily::All,
nsIGfxInfo::FEATURE_WEBRENDER,
nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
V(17, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 17.0.0.0");
// Mesa baseline for non-Intel/NVIDIA/ATI devices. These other devices will // often have less mature drivers so let's block older Mesa versions.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::MesaNonIntelNvidiaAtiAll,
DeviceFamily::All, nsIGfxInfo::FEATURE_WEBRENDER,
nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
V(22, 2, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA_OTHER", "Mesa 22.2.0.0");
// Bug 1690568 / Bug 1393793 - Require Mesa 17.3.0+ for devices using the // AMD r600 driver to avoid shader compilation issues.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::MesaR600, DeviceFamily::All,
nsIGfxInfo::FEATURE_WEBRENDER,
nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
V(17, 3, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA_R600", "Mesa 17.3.0.0");
// Disable on all ATI devices not using Mesa for now.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::NonMesaAll, DeviceFamily::AtiAll,
nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_ATI", "");
// Disable R600 GPUs with Mesa drivers. // Bug 1673939 - Garbled text on RS880 GPUs with Mesa drivers.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::MesaAll, DeviceFamily::AmdR600,
nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_BUG_1673939", "https://gitlab.freedesktop.org/mesa/mesa/-/issues/3720");
// Bug 1635186 - Poor performance with video playing in a background window // on XWayland. Keep in sync with FEATURE_X11_EGL below to only enable them // together by default. Only Mesa and Nvidia binary drivers are expected // on Wayland right now.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::XWayland, DriverVendor::MesaAll, DeviceFamily::All,
nsIGfxInfo::FEATURE_WEBRENDER,
nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
V(17, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_BUG_1635186", "Mesa 17.0.0.0");
// Disable on all AMD devices not using Mesa.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::NonMesaAll, DeviceFamily::AtiAll,
nsIGfxInfo::FEATURE_X11_EGL, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_FAILURE_X11_EGL_NO_LINUX_ATI", "");
//////////////////////////////////// // FEATURE_DMABUF // Disabled due to high volume crash tracked in bug 1788573, fixed in the // 545 driver.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::NonMesaAll, DeviceFamily::NvidiaAll,
nsIGfxInfo::FEATURE_DMABUF, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_LESS_THAN, V(545, 23, 6, 0), "FEATURE_FAILURE_BUG_1788573", "");
// Disabled due to high volume crash tracked in bug 1913778. It appears that // only this version of the driver is affected.
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
WindowProtocol::All, DriverVendor::MesaRadeonsi, DeviceFamily::AtiAll,
nsIGfxInfo::FEATURE_DMABUF, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_EQUAL, V(24, 1, 3, 0), "FEATURE_FAILURE_BUG_1913778", "");
{
NS_ENSURE_ARG_POINTER(aStatus);
*aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
aSuggestedDriverVersion.SetIsVoid(true);
OperatingSystem os = OperatingSystem::Linux; if (aOS) *aOS = os;
if (sShutdownOccurred) { return NS_OK;
}
GetData();
if (mGlxTestError) { // If glxtest failed, block most features by default. if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED";
} else {
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
} return NS_OK;
}
if (mGLMajorVersion == 1) { // We're on OpenGL 1. In most cases that indicates really old hardware. // We better block them, rather than rely on them to fail gracefully, // because they don't! see bug 696636 if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_OPENGL_1";
} else {
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
} return NS_OK;
}
// Blocklist software GL implementations from using layers acceleration. // On the test infrastructure, we'll force-enable layers acceleration. if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && !mIsAccelerated &&
!PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_SOFTWARE_GL"; return NS_OK;
}
if (aFeature == nsIGfxInfo::FEATURE_WEBRENDER) { // Don't try Webrender on devices where we are guaranteed to fail. if (mGLMajorVersion < 3) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_OPENGL_LESS_THAN_3"; return NS_OK;
}
// Bug 1710400: Disable Webrender on the deprecated Intel DDX driver for (const nsCString& driver : mDdxDrivers) { if (strcasestr(driver.get(), "Intel")) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_DDX_INTEL"; return NS_OK;
}
}
}
NS_IMETHODIMP
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) { // This is never the case, as the active GPU should be the primary GPU.
*aIsGPU2Active = false; return NS_OK;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.