almarklein/visvis

Error using Wayland and Qt

sleepywitti opened this issue · 4 comments

Hello,
I recently switched to Wayland and noticed that visvis was not working within a QtWidget (using Qt 5.15.2, wayland 1.19.0 and visvis's pyside2 backend). It does not crash, but it produced some transparent canvas in the Qt application and printed the following error:

Traceback (most recent call last):
File "$HOME/.local/lib/python3.9/site-packages/visvis/backends/qtcommon.py", line 258, in paintEvent
self.figure.OnDraw()
File "$HOME/.local/lib/python3.9/site-packages/visvis/core/baseFigure.py", line 799, in OnDraw
self._pickerHelper.CaptureScreen()
File "$HOME/.local/lib/python3.9/site-packages/visvis/core/baseFigure.py", line 91, in CaptureScreen
self.screen = np.flipud( _Screenshot() )
File "$HOME/.local/lib/python3.9/site-packages/visvis/core/axes.py", line 41, in _Screenshot
gl.glReadBuffer(gl.GL_BACK)
File "$HOME/.local/lib/python3.9/site-packages/OpenGL/platform/baseplatform.py", line 415, in __call__
return self( *args, **named )
File "$HOME/.local/lib/python3.9/site-packages/OpenGL/error.py", line 230, in glCheckError
raise self._errorClass(
OpenGL.error.GLError: GLError(
err = 1282,
description = b'invalid operation',
baseOperation = glReadBuffer,
cArguments = (GL_BACK,)
)

I didn't had a deeper look into the error, but found the following workaround: Qt will fallback to X11/Wayland if WAYLAND_DISPLAY and QT_QPA_PLATFORM are unset. This can be done by calling the script using
env WAYLAND_DISPLAY="" QT_QPA_PLATFORM="" python ...
or directly enforcing this in the code itself before importing Qt:

import os
os.environ['WAYLAND_DISPLAY'] = ''
os.environ['QT_QPA_PLATFORM'] = ''

Maybe this helps if somebody gets the same error.

For completeness, here a small script that reproduced the error

from PySide2 import QtWidgets
import visvis as vv
vv_app = vv.use('pyside2')
Figure = vv_app.GetFigureClass()

app = QtWidgets.QApplication()

w = QtWidgets.QWidget()
vv_fig = Figure(w)

layout = QtWidgets.QHBoxLayout()
layout.addWidget(vv_fig._widget)

w.setLayout(layout)
w.show()
app.exec_()

having WAYLAND_DISPLAY=wayland-0 and QT_QPA_PLATFORM=wayland

Best
sleepywitti

Thanks for reporting this and even providing a solution!

For reference, one can detect Wayland like this: is_wayland = "wayland" in os.getenv("XDG_SESSION_TYPE", "").lower()

So we could add some code that applies the environment changes in this case. Though it might be that the environment will have to be set before importing Qt, in which case it's better to leave this up to the user ...

I agree with not putting it into the code of visvis, but leave the decision to the user. Probably a note in the wiki might be the best place to to put some note about wayland.

Added a note here: https://github.com/almarklein/visvis/wiki/Installation

edit: will also add a note in the FAQ

I recently added the glfw backend, which also has Wayland support. Last time I tested (the code was copied from wgpu-py) Wayland support was not perfect, but maybe better than Pyside?