diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-04-01 15:36:26 (GMT) |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2011-04-01 15:47:51 (GMT) |
commit | 991f59a295e7678165b1db7befc9beac8bdbe503 (patch) | |
tree | aeb8d58444baae4e412a7eddd9fa12cd2aaae863 /src | |
parent | 33ca59cd1827195cb7ef91a18c0775568471d4ce (diff) | |
download | Qt-991f59a295e7678165b1db7befc9beac8bdbe503.zip Qt-991f59a295e7678165b1db7befc9beac8bdbe503.tar.gz Qt-991f59a295e7678165b1db7befc9beac8bdbe503.tar.bz2 |
Moved all XCB event handling back into the main thread.
There are to many synchronization problems if any GL call can lead the
event processing thread to stall.
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 241 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 23 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindowsurface.cpp | 23 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindowsurface.h | 3 |
6 files changed, 86 insertions, 210 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index d1171b8..19a9503 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -137,7 +137,6 @@ void QGLXContext::createDefaultSharedContext(QXcbScreen *screen) void QGLXContext::makeCurrent() { Q_XCB_NOOP(m_screen->connection()); - m_screen->connection()->setEventProcessingEnabled(false); QPlatformGLContext::makeCurrent(); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context); Q_XCB_NOOP(m_screen->connection()); @@ -148,7 +147,6 @@ void QGLXContext::doneCurrent() Q_XCB_NOOP(m_screen->connection()); QPlatformGLContext::doneCurrent(); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); - m_screen->connection()->setEventProcessingEnabled(true); Q_XCB_NOOP(m_screen->connection()); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 05d3440..ec1fc1b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -47,6 +47,7 @@ #include <QtAlgorithms> #include <QSocketNotifier> #include <QtGui/private/qapplication_p.h> +#include <QAbstractEventDispatcher> #include <QtCore/QDebug> @@ -76,8 +77,6 @@ extern "C" { QXcbConnection::QXcbConnection(const char *displayName) : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) - , m_pauseId(0) - , m_enabled(true) #ifdef XCB_USE_DRI2 , m_dri2_major(0) , m_dri2_minor(0) @@ -114,12 +113,6 @@ QXcbConnection::QXcbConnection(const char *displayName) xcb_screen_next(&it); } - m_connectionEventListener = xcb_generate_id(xcb_connection()); - xcb_create_window(xcb_connection(), XCB_COPY_FROM_PARENT, - m_connectionEventListener, m_screens.at(0)->root(), - 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, - m_screens.at(0)->screen()->root_visual, 0, 0); - m_keyboard = new QXcbKeyboard(this); initializeAllAtoms(); @@ -128,50 +121,15 @@ QXcbConnection::QXcbConnection(const char *displayName) initializeDri2(); #endif - start(); -} + QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents())); -void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom atom, uint id) -{ - xcb_client_message_event_t event; - memset(&event, 0, sizeof(event)); - - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.sequence = 0; - event.window = m_connectionEventListener; - event.type = atom; - event.data.data32[0] = id; - - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event)); - xcb_flush(xcb_connection()); -} - -void QXcbConnection::setEventProcessingEnabled(bool enabled) -{ - if (enabled == m_enabled) - return; - - if (!enabled) { - sendConnectionEvent(QXcbAtom::_QT_PAUSE_CONNECTION, uint(m_pauseId)); - m_connectionLock.lock(); - m_pauseId.fetchAndAddOrdered(1); - } else { - m_connectionLock.unlock(); - m_connectionWaitCondition.wakeAll(); - } - - m_enabled = enabled; + QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(qApp->thread()); + connect(dispatcher, SIGNAL(awake()), this, SLOT(processXcbEvents())); } QXcbConnection::~QXcbConnection() { - setEventProcessingEnabled(true); - - sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION); - wait(); - - xcb_destroy_window(xcb_connection(), m_connectionEventListener); qDeleteAll(m_screens); #ifdef XCB_USE_XLIB @@ -417,128 +375,93 @@ void QXcbConnection::log(const char *file, int line, int sequence) info.sequence = sequence; info.file = file; info.line = line; - - QMutexLocker locker(&m_callLogMutex); - m_callLog << info; } #endif -void QXcbConnection::run() +void QXcbConnection::processXcbEvents() { - QMutexLocker locker(&m_connectionLock); - fd_set readset; - int xcb_fd = xcb_get_file_descriptor(xcb_connection()); - FD_ZERO(&readset); - FD_SET(xcb_fd, &readset); - int result; - while (true) { - while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) { - bool handled = true; - - uint response_type = event->response_type & ~0x80; - - if (!response_type) { - xcb_generic_error_t *error = (xcb_generic_error_t *)event; - - uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); - uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); - - printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n", - int(error->error_code), xcb_errors[clamped_error_code], - int(error->sequence), int(error->resource_id), - int(error->major_code), xcb_protocol_request_codes[clamped_major_code], - int(error->minor_code)); -#ifdef Q_XCB_DEBUG - QMutexLocker locker(&m_callLogMutex); - int i = 0; - for (; i < m_callLog.size(); ++i) { - if (m_callLog.at(i).sequence == error->sequence) { - printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); - break; - } else if (m_callLog.at(i).sequence > error->sequence) { - printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); - if (i > 0) - printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line); - break; - } - } - if (i == m_callLog.size() && !m_callLog.isEmpty()) - printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line); -#endif - continue; - } + while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) { + bool handled = true; -#ifdef Q_XCB_DEBUG - { - QMutexLocker locker(&m_callLogMutex); - int i = 0; - for (; i < m_callLog.size(); ++i) - if (m_callLog.at(i).sequence >= event->sequence) - break; - m_callLog.remove(0, i); - } -#endif + uint response_type = event->response_type & ~0x80; - if (response_type == XCB_CLIENT_MESSAGE) { - xcb_client_message_event_t *ev = (xcb_client_message_event_t *)event; + if (!response_type) { + xcb_generic_error_t *error = (xcb_generic_error_t *)event; - if (ev->type == QXcbAtom::_QT_CLOSE_CONNECTION) - return; + uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); + uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); - if (ev->type == QXcbAtom::_QT_PAUSE_CONNECTION) { - if (ev->data.data32[0] == uint(m_pauseId)) - m_connectionWaitCondition.wait(&m_connectionLock); - continue; + printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n", + int(error->error_code), xcb_errors[clamped_error_code], + int(error->sequence), int(error->resource_id), + int(error->major_code), xcb_protocol_request_codes[clamped_major_code], + int(error->minor_code)); +#ifdef Q_XCB_DEBUG + int i = 0; + for (; i < m_callLog.size(); ++i) { + if (m_callLog.at(i).sequence == error->sequence) { + printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); + break; + } else if (m_callLog.at(i).sequence > error->sequence) { + printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); + if (i > 0) + printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line); + break; } } - - switch (response_type) { - case XCB_EXPOSE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); - case XCB_BUTTON_PRESS: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); - case XCB_BUTTON_RELEASE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); - case XCB_MOTION_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); - case XCB_CONFIGURE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); - case XCB_CLIENT_MESSAGE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); - case XCB_ENTER_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); - case XCB_LEAVE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); - case XCB_FOCUS_IN: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); - case XCB_FOCUS_OUT: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); - case XCB_KEY_PRESS: - HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); - case XCB_KEY_RELEASE: - HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); - case XCB_MAPPING_NOTIFY: - m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); - break; - default: - handled = false; - break; - } - if (handled) - printXcbEvent("Handled XCB event", event); - else - printXcbEvent("Unhandled XCB event", event); + if (i == m_callLog.size() && !m_callLog.isEmpty()) + printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line); +#endif + continue; } - do { - result = select(xcb_fd + 1, &readset, 0, 0, 0); - } while (result == -1 && errno == EINTR); - - if (result <= 0 || !FD_ISSET(xcb_fd, &readset)) - continue; +#ifdef Q_XCB_DEBUG + { + int i = 0; + for (; i < m_callLog.size(); ++i) + if (m_callLog.at(i).sequence >= event->sequence) + break; + m_callLog.remove(0, i); + } +#endif + switch (response_type) { + case XCB_EXPOSE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); + case XCB_BUTTON_PRESS: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); + case XCB_BUTTON_RELEASE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); + case XCB_MOTION_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + case XCB_CONFIGURE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); + case XCB_CLIENT_MESSAGE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); + case XCB_ENTER_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); + case XCB_LEAVE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); + case XCB_FOCUS_IN: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); + case XCB_FOCUS_OUT: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); + case XCB_KEY_PRESS: + HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + case XCB_KEY_RELEASE: + HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); + case XCB_MAPPING_NOTIFY: + m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); + break; + default: + handled = false; + break; + } + if (handled) + printXcbEvent("Handled XCB event", event); + else + printXcbEvent("Unhandled XCB event", event); } - fprintf(stderr, "I/O error in xcb_wait_for_event\n"); } static const char * xcb_atomnames = { @@ -580,9 +503,6 @@ static const char * xcb_atomnames = { "_QT_SCROLL_DONE\0" "_QT_INPUT_ENCODING\0" - "_QT_CLOSE_CONNECTION\0" - "_QT_PAUSE_CONNECTION\0" - "_MOTIF_WM_HINTS\0" "DTWM_IS_RUNNING\0" @@ -738,13 +658,8 @@ void QXcbConnection::initializeAllAtoms() { void QXcbConnection::sync() { // from xcb_aux_sync - bool wasEnabled = m_enabled; - setEventProcessingEnabled(false); xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection())); free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); - - if (wasEnabled) - setEventProcessingEnabled(true); } #if defined(XCB_USE_EGL) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7088184..53846f1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -44,10 +44,8 @@ #include <xcb/xcb.h> #include <QList> -#include <QMutex> +#include <QObject> #include <QVector> -#include <QWaitCondition> -#include <QThread> #define Q_XCB_DEBUG @@ -93,10 +91,6 @@ namespace QXcbAtom { _QT_SCROLL_DONE, _QT_INPUT_ENCODING, - // Qt/XCB specific - _QT_CLOSE_CONNECTION, - _QT_PAUSE_CONNECTION, - _MOTIF_WM_HINTS, DTWM_IS_RUNNING, @@ -222,7 +216,7 @@ namespace QXcbAtom { class QXcbKeyboard; -class QXcbConnection : public QThread +class QXcbConnection : public QObject { Q_OBJECT public: @@ -242,8 +236,6 @@ public: QXcbKeyboard *keyboard() const { return m_keyboard; } - void setEventProcessingEnabled(bool enabled); - #ifdef XCB_USE_XLIB void *xlib_display() const { return m_xlib_display; } #endif @@ -261,8 +253,8 @@ public: void sync(); -protected: - void run(); +private slots: + void processXcbEvents(); private: void initializeAllAtoms(); @@ -281,12 +273,6 @@ private: QByteArray m_displayName; - xcb_window_t m_connectionEventListener; - QMutex m_connectionLock; - QWaitCondition m_connectionWaitCondition; - QAtomicInt m_pauseId; - bool m_enabled; - QXcbKeyboard *m_keyboard; #if defined(XCB_USE_XLIB) @@ -311,7 +297,6 @@ private: int line; }; QVector<CallInfo> m_callLog; - QMutex m_callLogMutex; void log(const char *file, int line, int sequence); template <typename cookie_t> friend cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, int line); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 7aeb557..1f4a13c 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -113,7 +113,6 @@ QXcbWindow::QXcbWindow(QWidget *tlw) if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL && QApplicationPrivate::platformIntegration()->hasOpenGL()) { - connection()->setEventProcessingEnabled(false); #if defined(XCB_USE_GLX) XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat()); #elif defined(XCB_USE_EGL) @@ -142,7 +141,6 @@ QXcbWindow::QXcbWindow(QWidget *tlw) } else { qFatal("no window!"); } - connection()->setEventProcessingEnabled(true); } else #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { @@ -431,7 +429,6 @@ QPlatformGLContext *QXcbWindow::glContext() const return 0; } if (!m_context) { - connection()->setEventProcessingEnabled(false); #if defined(XCB_USE_GLX) QXcbWindow *that = const_cast<QXcbWindow *>(this); that->m_context = new QGLXContext(m_window, m_screen, widget()->platformWindowFormat()); @@ -450,7 +447,6 @@ QPlatformGLContext *QXcbWindow::glContext() const QXcbWindow *that = const_cast<QXcbWindow *>(this); that->m_context = new QDri2Context(that); #endif - connection()->setEventProcessingEnabled(true); } return m_context; } diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp index 4c0d862..a4607dc 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp @@ -62,7 +62,7 @@ public: QImage *image() { return &m_qimage; } void put(xcb_window_t window, const QPoint &dst, const QRect &source); - void preparePaint(const QRegion ®ion, QMutex *mutex); + void preparePaint(const QRegion ®ion); private: void destroy(); @@ -148,15 +148,12 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s Q_XCB_NOOP(connection()); } -void QXcbShmImage::preparePaint(const QRegion ®ion, QMutex *mutex) +void QXcbShmImage::preparePaint(const QRegion ®ion) { // to prevent X from reading from the image region while we're writing to it if (m_dirty.intersects(region)) { connection()->sync(); - mutex->lock(); m_dirty = QRegion(); - } else { - mutex->lock(); } } @@ -170,7 +167,6 @@ QXcbWindowSurface::QXcbWindowSurface(QWidget *widget, bool setDefaultSurface) QXcbWindowSurface::~QXcbWindowSurface() { - QMutexLocker locker(&m_surfaceLock); delete m_image; } @@ -181,12 +177,11 @@ QPaintDevice *QXcbWindowSurface::paintDevice() void QXcbWindowSurface::beginPaint(const QRegion ®ion) { - m_image->preparePaint(region, &m_surfaceLock); + m_image->preparePaint(region); } void QXcbWindowSurface::endPaint(const QRegion &) { - m_surfaceLock.unlock(); } void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) @@ -201,8 +196,6 @@ void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoi extern QWidgetData* qt_widget_data(QWidget *); QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft(); - QMutexLocker locker(&m_surfaceLock); - QVector<QRect> rects = region.rects(); for (int i = 0; i < rects.size(); ++i) m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset)); @@ -217,15 +210,9 @@ void QXcbWindowSurface::resize(const QSize &size) QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(window())); - connection()->setEventProcessingEnabled(false); - m_surfaceLock.lock(); - delete m_image; m_image = new QXcbShmImage(screen, size); Q_XCB_NOOP(connection()); - - m_surfaceLock.unlock(); - connection()->setEventProcessingEnabled(true); } extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); @@ -235,14 +222,12 @@ bool QXcbWindowSurface::scroll(const QRegion &area, int dx, int dy) if (m_image->image()->isNull()) return false; - m_image->preparePaint(area, &m_surfaceLock); + m_image->preparePaint(area); const QVector<QRect> rects = area.rects(); for (int i = 0; i < rects.size(); ++i) qt_scrollRectInImage(*m_image->image(), rects.at(i), QPoint(dx, dy)); - m_surfaceLock.unlock(); - return true; } diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.h b/src/plugins/platforms/xcb/qxcbwindowsurface.h index e508fe6..f87e122 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.h +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.h @@ -48,8 +48,6 @@ #include "qxcbobject.h" -#include <QMutex> - class QXcbShmImage; class QXcbWindowSurface : public QXcbObject, public QWindowSurface @@ -68,7 +66,6 @@ public: private: QXcbShmImage *m_image; - QMutex m_surfaceLock; }; #endif |