diff options
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 21 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 16 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 13 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 7 |
5 files changed, 58 insertions, 7 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index 45ccd9929e..3ce0041aeb 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -523,11 +523,11 @@ void QGLXContext::swapBuffers(QPlatformSurface *surface) if (surface->surface()->surfaceClass() == QSurface::Window) { QXcbWindow *platformWindow = static_cast<QXcbWindow *>(surface); - // OpenGL context might be bound to a non-gui thread - // use QueuedConnection to sync the window from the platformWindow's thread - // as QXcbWindow is no QObject, a wrapper slot in QXcbConnection is used. + // OpenGL context might be bound to a non-gui thread use QueuedConnection to sync + // the window from the platformWindow's thread as QXcbWindow is no QObject, an + // event is sent to QXcbConnection. (this is faster than a metacall) if (platformWindow->needsSync()) - QMetaObject::invokeMethod(m_screen->connection(), "syncWindow", Qt::QueuedConnection, Q_ARG(QXcbWindow*, platformWindow)); + platformWindow->postSyncWindowRequest(); } } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 7f23c84cb9..a2ce392151 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1842,9 +1842,26 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() return m_systemTrayTracker; } -void QXcbConnection::syncWindow(QXcbWindow *window) +bool QXcbConnection::event(QEvent *e) { - window->updateSyncRequestCounter(); + if (e->type() == QEvent::User + 1) { + QXcbSyncWindowRequest *ev = static_cast<QXcbSyncWindowRequest *>(e); + QXcbWindow *w = ev->window(); + if (w) { + w->updateSyncRequestCounter(); + ev->invalidate(); + } + return true; + } + return QObject::event(e); +} + +void QXcbSyncWindowRequest::invalidate() +{ + if (m_window) { + m_window->clearSyncWindowRequest(); + m_window = 0; + } } QXcbConnectionGrabber::QXcbConnectionGrabber(QXcbConnection *connection) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 354ba54e70..9e9865a2e9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -355,6 +355,18 @@ public: typedef QHash<xcb_window_t, QXcbWindowEventListener *> WindowMapper; +class QXcbSyncWindowRequest : public QEvent +{ +public: + QXcbSyncWindowRequest(QXcbWindow *w) : QEvent(QEvent::Type(QEvent::User + 1)), m_window(w) { } + + QXcbWindow *window() const { return m_window; } + void invalidate(); + +private: + QXcbWindow *m_window; +}; + class QAbstractEventDispatcher; class QXcbConnection : public QObject { @@ -468,8 +480,10 @@ public: QXcbEventReader *eventReader() const { return m_reader; } +protected: + bool event(QEvent *e) Q_DECL_OVERRIDE; + public slots: - void syncWindow(QXcbWindow *window); void flush() { xcb_flush(m_connection); } private slots: diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 787fdb6641..a127ac0293 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -223,6 +223,7 @@ QXcbWindow::QXcbWindow(QWindow *window) #endif , m_lastWindowStateEvent(-1) , m_syncState(NoSyncNeeded) + , m_pendingSyncRequest(0) { m_screen = static_cast<QXcbScreen *>(window->screen()->handle()); @@ -565,6 +566,9 @@ void QXcbWindow::destroy() delete m_eglSurface; m_eglSurface = 0; #endif + + if (m_pendingSyncRequest) + m_pendingSyncRequest->invalidate(); } void QXcbWindow::setGeometry(const QRect &rect) @@ -2371,4 +2375,13 @@ bool QXcbWindow::needsSync() const return m_syncState == SyncAndConfigureReceived; } +void QXcbWindow::postSyncWindowRequest() +{ + if (!m_pendingSyncRequest) { + QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); + m_pendingSyncRequest = e; + QCoreApplication::postEvent(m_screen->connection(), e); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 72b5c7bcc9..a8cadd8e6c 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -57,7 +57,9 @@ QT_BEGIN_NAMESPACE class QXcbScreen; class QXcbEGLSurface; +class QXcbSyncWindowRequest; class QIcon; + class QXcbWindow : public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow { public: @@ -159,6 +161,9 @@ public: bool needsSync() const; + void postSyncWindowRequest(); + void clearSyncWindowRequest() { m_pendingSyncRequest = 0; } + public Q_SLOTS: void updateSyncRequestCounter(); @@ -235,6 +240,8 @@ private: SyncAndConfigureReceived }; SyncState m_syncState; + + QXcbSyncWindowRequest *m_pendingSyncRequest; }; QT_END_NAMESPACE |