diff --git a/doc/changes/devel/13012.bugfix.rst b/doc/changes/devel/13012.bugfix.rst new file mode 100644 index 00000000000..2d0a324ba06 --- /dev/null +++ b/doc/changes/devel/13012.bugfix.rst @@ -0,0 +1 @@ +Fix errant detection of software-rendered vs hardware-rendered MESA GL contexts in 3D rendering on Linux, by `Eric Larson`_. diff --git a/doc/install/advanced.rst b/doc/install/advanced.rst index 0fe5a5e324a..61c7bc07aa3 100644 --- a/doc/install/advanced.rst +++ b/doc/install/advanced.rst @@ -281,6 +281,20 @@ of VTK and/or QT are incompatible. This series of commands should fix it: If you installed VTK using ``pip`` rather than ``conda``, substitute the first line for ``pip uninstall -y vtk``. +3D plotting trouble on Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are having trouble with 3D plotting on Linux, one possibility is that you +are using Wayland for graphics. To check, you can do: + +.. code-block:: console + + $ echo $XDG_SESSION_TYPE + wayland + +If so, you will need to tell Qt to use X11 instead of Wayland. You can do this +by setting ``export QT_QPA_PLATFORM=xcb`` in your terminal session. To make it +permanent for your logins, you can set it for example in ``~/.profile``. .. LINKS diff --git a/mne/viz/backends/_pyvista.py b/mne/viz/backends/_pyvista.py index 85060837729..620793ca47a 100644 --- a/mne/viz/backends/_pyvista.py +++ b/mne/viz/backends/_pyvista.py @@ -837,7 +837,7 @@ def _toggle_antialias(self): """Enable it everywhere except on systems with problematic OpenGL.""" # MESA can't seem to handle MSAA and depth peeling simultaneously, see # https://github.com/pyvista/pyvista/issues/4867 - bad_system = _is_mesa(self.plotter) + bad_system = _is_osmesa(self.plotter) for plotter in self._all_plotters: if bad_system or not self.antialias: plotter.disable_anti_aliasing() @@ -1319,10 +1319,11 @@ def _disabled_depth_peeling(): depth_peeling["enabled"] = depth_peeling_enabled -def _is_mesa(plotter): +def _is_osmesa(plotter): # MESA (could use GPUInfo / _get_gpu_info here, but it takes # > 700 ms to make a new window + report capabilities!) # CircleCI's is: "Mesa 20.0.8 via llvmpipe (LLVM 10.0.0, 256 bits)" + # and a working Nouveau is: "Mesa 24.2.3-1ubuntu1 via NVE6" if platform.system() == "Darwin": # segfaults on macOS sometimes return False gpu_info_full = plotter.ren_win.ReportCapabilities() @@ -1331,8 +1332,9 @@ def _is_mesa(plotter): gpu_info_full, ) gpu_info = " ".join(gpu_info).lower() - is_mesa = "mesa" in gpu_info.split() - if is_mesa: + is_osmesa = "mesa" in gpu_info.split() + print(is_osmesa) + if is_osmesa: # Try to warn if it's ancient version = re.findall("mesa ([0-9.]+)[ -].*", gpu_info) or re.findall( "OpenGL version string: .* Mesa ([0-9.]+)\n", gpu_info_full @@ -1345,7 +1347,8 @@ def _is_mesa(plotter): "surface rendering, consider upgrading to 18.3.6 or " "later." ) - return is_mesa + is_osmesa = "via llvmpipe" in gpu_info + return is_osmesa class _SafeBackgroundPlotter(BackgroundPlotter): diff --git a/mne/viz/backends/_qt.py b/mne/viz/backends/_qt.py index b1cd43788ef..259b8da5e1d 100644 --- a/mne/viz/backends/_qt.py +++ b/mne/viz/backends/_qt.py @@ -102,7 +102,6 @@ _check_3d_figure, # noqa: F401 _close_3d_figure, # noqa: F401 _close_all, # noqa: F401 - _is_mesa, # noqa: F401 _PyVistaRenderer, _set_3d_title, # noqa: F401 _set_3d_view, # noqa: F401 diff --git a/mne/viz/backends/tests/test_renderer.py b/mne/viz/backends/tests/test_renderer.py index a52942c804b..2c524f4145f 100644 --- a/mne/viz/backends/tests/test_renderer.py +++ b/mne/viz/backends/tests/test_renderer.py @@ -217,16 +217,21 @@ def fail(x): def test_3d_warning(renderer_pyvistaqt, monkeypatch): """Test that warnings are emitted for old Mesa.""" fig = renderer_pyvistaqt.create_3d_figure((800, 600)) - _is_mesa = renderer_pyvistaqt.backend._is_mesa + from mne.viz.backends._pyvista import _is_osmesa + plotter = fig.plotter - good = "OpenGL renderer string: OpenGL 3.3 (Core Profile) Mesa 20.0.8 via llvmpipe (LLVM 10.0.0, 256 bits)\n" # noqa - bad = "OpenGL renderer string: OpenGL 3.3 (Core Profile) Mesa 18.3.4 via llvmpipe (LLVM 7.0, 256 bits)\n" # noqa + pre = "OpenGL renderer string: " + good = f"{pre}OpenGL 3.3 (Core Profile) Mesa 20.0.8 via llvmpipe (LLVM 10.0.0, 256 bits)\n" # noqa + bad = f"{pre}OpenGL 3.3 (Core Profile) Mesa 18.3.4 via llvmpipe (LLVM 7.0, 256 bits)\n" # noqa monkeypatch.setattr(platform, "system", lambda: "Linux") # avoid short-circuit monkeypatch.setattr(plotter.ren_win, "ReportCapabilities", lambda: good) - assert _is_mesa(plotter) + assert _is_osmesa(plotter) monkeypatch.setattr(plotter.ren_win, "ReportCapabilities", lambda: bad) with pytest.warns(RuntimeWarning, match=r"18\.3\.4 is too old"): - assert _is_mesa(plotter) - non = "OpenGL 4.1 Metal - 76.3 via Apple M1 Pro\n" + assert _is_osmesa(plotter) + non = f"{pre}OpenGL 4.1 Metal - 76.3 via Apple M1 Pro\n" + monkeypatch.setattr(plotter.ren_win, "ReportCapabilities", lambda: non) + assert not _is_osmesa(plotter) + non = f"{pre}OpenGL 4.5 (Core Profile) Mesa 24.2.3-1ubuntu1 via NVE6\n" monkeypatch.setattr(plotter.ren_win, "ReportCapabilities", lambda: non) - assert not _is_mesa(plotter) + assert not _is_osmesa(plotter)