[kwin_waylnad] Fix support for QtWayland's client buffer integration

QtWayland performs an eglInitialize in the main thread when for the first
time an OpenGL context/window is needed. In KWin's startup this happens
during initializing Scripting which creates a QDesktopWidget and triggers
the creation of a QWindow with a RasterGLSurface.

Calling eglInitialize in the main thread blocks as it calls wl_roundtrip.
We cannot just disable OpenGL as that would mean that we cannot use
QtQuick.

The workaround in this change is to create a QWindow with a
RasterGLSurface in a thread and call create on it. This ensures that
OpenGL gets initialized in the thread and doesn't block.
This commit is contained in:
Martin Gräßlin 2015-02-25 11:42:56 +01:00
parent 54c2c5db2d
commit 9dcd123438

View file

@ -39,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QSocketNotifier> #include <QSocketNotifier>
#include <QThread> #include <QThread>
#include <QDebug> #include <QDebug>
#include <QWindow>
// system // system
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
@ -165,12 +166,29 @@ void ApplicationWayland::continueStartupWithX()
::exit(1); ::exit(1);
} }
// HACK: create a QWindow in a thread to force QtWayland to create the client buffer integration
// this performs an eglInitialize which would block as it does a roundtrip to the Wayland server
// in the main thread. By moving into a thread we get the initialize without hitting the problem
// This needs to be done before creating the Workspace as from inside Workspace the dangerous code
// gets hit in the main thread
QFutureWatcher<void> *eglInitWatcher = new QFutureWatcher<void>(this);
connect(eglInitWatcher, &QFutureWatcher<void>::finished, this,
[this, eglInitWatcher] {
eglInitWatcher->deleteLater();
createWorkspace(); createWorkspace();
Xcb::sync(); // Trigger possible errors, there's still a chance to abort Xcb::sync(); // Trigger possible errors, there's still a chance to abort
notifyKSplash(); notifyKSplash();
} }
);
eglInitWatcher->setFuture(QtConcurrent::run([] {
QWindow w;
w.setSurfaceType(QSurface::RasterGLSurface);
w.create();
}));
}
void ApplicationWayland::createX11Connection() void ApplicationWayland::createX11Connection()
{ {