summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbwindow.cpp
diff options
context:
space:
mode:
authorMartin Gräßlin <mgraesslin@kde.org>2014-05-20 13:01:50 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-27 19:31:49 +0200
commit8746a6a3e2a21f952badd6301565783f07f61c03 (patch)
tree017249ef1bf4c288b88f15e6c0269d21c4a23078 /src/plugins/platforms/xcb/qxcbwindow.cpp
parentd153e4628e7643cf02b795f68f739c4bced15389 (diff)
Improve the implementation of the _NET_WM_SYNC_REQUEST protocol
This change improves the synced resizes of xcb windows and adds support for synced resizes of glx windows. The QXcbWindow keeps a better track on whether the window manager expects a sync and can be in one of three states: * no sync required * sync required, but configure notify event not yet received * sync required and configured By tracking this in the QXcbWindow itself the backing store can make use of this information and doesn't need an own heuristic to decide whether a sync is needed. Also this allows to add support for synced resizes of windows with an OpenGLSurface. This is accomplished by checking the sync state after swapping buffers. As the OpenGL context may be bound to a background thread the sync is done using a QueuedConnection to ensure that the sync happens in the thread which created the xcb window. So far this is only added for GLX. This significantly improves the resize experience of QQuickWindow and also the initial mapping with a composited window manager in case the compositor uses the sync protocol to determine whether the window is ready to get painted on screen. Change-Id: Ied0261873043d785dec652d2821fc3638292fa36 Reviewed-by: Uli Schlachter <psychon@znc.in> Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 3645b6469a..a46fe437d8 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -200,6 +200,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
, m_eglSurface(0)
#endif
, m_lastWindowStateEvent(-1)
+ , m_syncState(NoSyncNeeded)
{
m_screen = static_cast<QXcbScreen *>(window->screen()->handle());
@@ -367,7 +368,12 @@ void QXcbWindow::create()
properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
- m_usingSyncProtocol = m_screen->syncRequestSupported() && window()->surfaceType() != QSurface::OpenGLSurface;
+ m_usingSyncProtocol = m_screen->syncRequestSupported();
+#if !defined(XCB_USE_GLX)
+ // synced resize only implemented on GLX
+ if (window()->supportsOpenGL())
+ m_usingSyncProtocol = false;
+#endif
if (m_usingSyncProtocol)
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
@@ -1596,6 +1602,8 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
connection()->setTime(event->data.data32[1]);
m_syncValue.lo = event->data.data32[2];
m_syncValue.hi = event->data.data32[3];
+ if (m_usingSyncProtocol)
+ m_syncState = SyncReceived;
#ifndef QT_NO_WHATSTHIS
} else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) {
QWindowSystemInterface::handleEnterWhatsThisEvent();
@@ -1669,6 +1677,9 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
+ if (m_usingSyncProtocol && m_syncState == SyncReceived)
+ m_syncState = SyncAndConfigureReceived;
+
m_dirtyFrameMargins = true;
}
@@ -1945,12 +1956,17 @@ void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *)
void QXcbWindow::updateSyncRequestCounter()
{
+ if (m_syncState != SyncAndConfigureReceived) {
+ // window manager does not expect a sync event yet.
+ return;
+ }
if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue));
- connection()->sync();
+ xcb_flush(xcb_connection());
m_syncValue.lo = 0;
m_syncValue.hi = 0;
+ m_syncState = NoSyncNeeded;
}
}
@@ -2173,4 +2189,9 @@ void QXcbWindow::setAlertState(bool enabled)
}
}
+bool QXcbWindow::needsSync() const
+{
+ return m_syncState == SyncAndConfigureReceived;
+}
+
QT_END_NAMESPACE