diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-04-07 14:25:02 (GMT) |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2011-04-07 14:26:59 (GMT) |
commit | c238398e8e120c870c7581dc3a415c5d8d910e88 (patch) | |
tree | 8ff6c62ce84ba6307c9678f6b1b53f8f83be9c3f /src/plugins/platforms/wayland | |
parent | 2149763b7293be2360beb3ec1fe9117c508eedd1 (diff) | |
download | Qt-c238398e8e120c870c7581dc3a415c5d8d910e88.zip Qt-c238398e8e120c870c7581dc3a415c5d8d910e88.tar.gz Qt-c238398e8e120c870c7581dc3a415c5d8d910e88.tar.bz2 |
Made wayland plugin single-threaded, yay :)
Not calling QApplication::processEvents() in qt_init any more, and not
using a write socket notifier to send data over the wayland protocol.
Diffstat (limited to 'src/plugins/platforms/wayland')
-rw-r--r-- | src/plugins/platforms/wayland/qwaylanddisplay.cpp | 111 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylanddisplay.h | 28 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandeventthread.cpp | 158 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandeventthread.h | 87 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindow.cpp | 14 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindow.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/wayland.pro | 6 |
7 files changed, 117 insertions, 288 deletions
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 4f456c9..e2bfaa2 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -45,12 +45,12 @@ #include "qwaylandscreen.h" #include "qwaylandcursor.h" #include "qwaylandinputdevice.h" -#include "qwaylandeventthread.h" #ifdef QT_WAYLAND_GL_SUPPORT #include "gl_integration/qwaylandglintegration.h" #endif +#include <QtCore/QAbstractEventDispatcher> #include <QtGui/QApplication> #include <unistd.h> @@ -113,24 +113,6 @@ const struct wl_shell_listener QWaylandDisplay::shellListener = { QWaylandDisplay::shellHandleConfigure, }; -void QWaylandDisplay::displayHandleGlobal(uint32_t id, QByteArray interface, uint32_t version) -{ - Q_UNUSED(version); - - if (interface == "compositor") { - mCompositor = wl_compositor_create(mDisplay, id); - } else if (interface == "shm") { - mShm = wl_shm_create(mDisplay, id); - } else if (interface == "shell"){ - mShell = wl_shell_create(mDisplay, id); - wl_shell_add_listener(mShell, &shellListener, this); - } else if (interface == "input_device") { - QWaylandInputDevice *inputDevice = - new QWaylandInputDevice(mDisplay, id); - mInputDevices.append(inputDevice); - } -} - QWaylandDisplay::QWaylandDisplay(void) { mDisplay = wl_display_connect(NULL); @@ -142,24 +124,29 @@ QWaylandDisplay::QWaylandDisplay(void) mEglIntegration = QWaylandGLIntegration::createGLIntegration(this); #endif - mEventThread = new QWaylandEventThread(this); - - - mEventThread->waitForScreens(); + qRegisterMetaType<uint32_t>("uint32_t"); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration->initialize(); #endif + connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(flushRequests())); + + wl_display_add_global_listener(mDisplay, QWaylandDisplay::displayHandleGlobal, this); + mFd = wl_display_get_fd(mDisplay, sourceUpdate, this); + mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this); + connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(readEvents())); + + waitForScreens(); } QWaylandDisplay::~QWaylandDisplay(void) { + close(mFd); #ifdef QT_WAYLAND_GL_SUPPORT delete mEglIntegration; #endif - delete mEventThread; wl_display_destroy(mDisplay); } @@ -179,3 +166,79 @@ void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data) wl_display_frame_callback(mDisplay, func, data); } +void QWaylandDisplay::flushRequests() +{ + if (mSocketMask & WL_DISPLAY_WRITABLE) + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); +} + +void QWaylandDisplay::readEvents() +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} + +int QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +{ + QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data); + waylandDisplay->mSocketMask = mask; + + return 0; +} + +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + //call back function called from another thread; + //but its safe to call createScreen from another thread since + //QWaylandScreen does a moveToThread + QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data); + QRect outputRect = QRect(x, y, width, height); + waylandDisplay->createNewScreen(output,outputRect); +} + +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +void QWaylandDisplay::waitForScreens() +{ + flushRequests(); + while (mScreens.isEmpty()) + readEvents(); +} + +void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, + void *data) +{ + Q_UNUSED(display); + QWaylandDisplay *that = static_cast<QWaylandDisplay *>(data); + that->displayHandleGlobal(id, QByteArray(interface), version); +} + +void QWaylandDisplay::displayHandleGlobal(uint32_t id, + const QByteArray &interface, + uint32_t version) +{ + Q_UNUSED(version); + + if (interface == "output") { + struct wl_output *output = wl_output_create(mDisplay, id); + wl_output_add_listener(output, &outputListener, this); + } else if (interface == "compositor") { + mCompositor = wl_compositor_create(mDisplay, id); + } else if (interface == "shm") { + mShm = wl_shm_create(mDisplay, id); + } else if (interface == "shell"){ + mShell = wl_shell_create(mDisplay, id); + wl_shell_add_listener(mShell, &shellListener, this); + } else if (interface == "input_device") { + QWaylandInputDevice *inputDevice = + new QWaylandInputDevice(mDisplay, id); + mInputDevices.append(inputDevice); + } +} diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h index 4cfb7b5..ac0ad71 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -55,8 +55,6 @@ class QWaylandBuffer; class QPlatformScreen; class QWaylandScreen; class QWaylandGLIntegration; -class QWaylandEventThread; - class QWaylandDisplay : public QObject { Q_OBJECT @@ -85,17 +83,39 @@ public: struct wl_display *wl_display() const { return mDisplay; } public slots: void createNewScreen(struct wl_output *output, QRect geometry); - void displayHandleGlobal(uint32_t id, QByteArray interface, uint32_t version); + void readEvents(); + void flushRequests(); private: + void waitForScreens(); + void displayHandleGlobal(uint32_t id, + const QByteArray &interface, + uint32_t version); + struct wl_display *mDisplay; - QWaylandEventThread *mEventThread; struct wl_compositor *mCompositor; struct wl_shm *mShm; struct wl_shell *mShell; QList<QPlatformScreen *> mScreens; QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; + int mFd; + bool mScreensInitialized; + + uint32_t mSocketMask; + + static const struct wl_output_listener outputListener; + static int sourceUpdate(uint32_t mask, void *data); + static void displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data); + static void outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height); + #ifdef QT_WAYLAND_GL_SUPPORT QWaylandGLIntegration *mEglIntegration; #endif diff --git a/src/plugins/platforms/wayland/qwaylandeventthread.cpp b/src/plugins/platforms/wayland/qwaylandeventthread.cpp deleted file mode 100644 index 1474d9c..0000000 --- a/src/plugins/platforms/wayland/qwaylandeventthread.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandeventthread.h" - -#include <QtCore/QMetaType> - -QWaylandEventThread::QWaylandEventThread(QWaylandDisplay *display) - : QObject() - , mDisplay(display) - , mReadNotifier(0) - , mWriteNotifier(0) - , mFd(0) - , mScreensInitialized(false) -{ - qRegisterMetaType<uint32_t>("uint32_t"); - QThread *thread = new QThread(this); - moveToThread(thread); - connect(thread,SIGNAL(started()),SLOT(runningInThread())); - thread->start(); - -} - -QWaylandEventThread::~QWaylandEventThread() -{ - close(mFd); -} - -void QWaylandEventThread::runningInThread() -{ - - wl_display_add_global_listener(mDisplay->wl_display(), - QWaylandEventThread::displayHandleGlobal, this); - int fd = wl_display_get_fd(mDisplay->wl_display(), sourceUpdate, this); - mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); - connect(mReadNotifier, - SIGNAL(activated(int)), this, SLOT(readEvents())); - - mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); - connect(mWriteNotifier, - SIGNAL(activated(int)), this, SLOT(flushRequests())); - mWriteNotifier->setEnabled(false); - - readEvents(); -} - - -int QWaylandEventThread::sourceUpdate(uint32_t mask, void *data) -{ - QWaylandEventThread *eventThread = (QWaylandEventThread *) data; - - /* FIXME: We get a callback here when we ask wl_display for the - * fd, but at that point we don't have the socket notifier as we - * need the fd to create that. We'll probably need to split that - * API into get_fd and set_update_func functions. */ - if (eventThread->mWriteNotifier == NULL) - return 0; - - QMetaObject::invokeMethod(eventThread->mWriteNotifier,"setEnabled",Qt::QueuedConnection, - Q_ARG(bool,mask & WL_DISPLAY_WRITABLE)); -// eventThread->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); - - return 0; -} - -void QWaylandEventThread::readEvents() -{ - wl_display_iterate(mDisplay->wl_display(), WL_DISPLAY_READABLE); -} - - -void QWaylandEventThread::flushRequests() -{ - wl_display_iterate(mDisplay->wl_display(), WL_DISPLAY_WRITABLE); -} - -void QWaylandEventThread::outputHandleGeometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - //call back function called from another thread; - //but its safe to call createScreen from another thread since - //QWaylandScreen does a moveToThread - QWaylandEventThread *waylandEventThread = static_cast<QWaylandEventThread *>(data); - QRect outputRect = QRect(x, y, width, height); - waylandEventThread->mDisplay->createNewScreen(output,outputRect); - waylandEventThread->mScreensInitialized = true; - waylandEventThread->mWaitForScreens.wakeAll(); -} - -const struct wl_output_listener QWaylandEventThread::outputListener = { - QWaylandEventThread::outputHandleGeometry -}; - -void QWaylandEventThread::displayHandleGlobal(wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, - void *data) -{ - if (strcmp(interface, "output") == 0) { - struct wl_output *output = wl_output_create(display, id); - wl_output_add_listener(output, &outputListener, data); - } - Q_UNUSED(display); - QWaylandEventThread *that = static_cast<QWaylandEventThread *>(data); - QByteArray interfaceByteArray(interface); - QMetaObject::invokeMethod(that->mDisplay,"displayHandleGlobal",Qt::QueuedConnection, - Q_ARG(uint32_t,id),Q_ARG(QByteArray,interfaceByteArray),Q_ARG(uint32_t,version)); -} - -void QWaylandEventThread::waitForScreens() -{ - QMutex lock; - lock.lock(); - if (!mScreensInitialized) { - mWaitForScreens.wait(&lock); - } -} diff --git a/src/plugins/platforms/wayland/qwaylandeventthread.h b/src/plugins/platforms/wayland/qwaylandeventthread.h deleted file mode 100644 index 7a5189e..0000000 --- a/src/plugins/platforms/wayland/qwaylandeventthread.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWAYLANDEVENTTHREAD_H -#define QWAYLANDEVENTTHREAD_H - -#include "qwaylanddisplay.h" - -#include <QtCore/QObject> -#include <QtCore/QThread> -#include <QtCore/QSocketNotifier> -#include <QtCore/QMutex> - -class QWaylandEventThread : public QObject -{ - Q_OBJECT -public: - explicit QWaylandEventThread(QWaylandDisplay *display); - ~QWaylandEventThread(); - - static int sourceUpdate(uint32_t mask, void *data); - - void waitForScreens(); - -signals: -public slots: - void runningInThread(); - void readEvents(); - void flushRequests(); -private: - QWaylandDisplay *mDisplay; - QSocketNotifier *mReadNotifier; - QSocketNotifier *mWriteNotifier; - int mFd; - QWaitCondition mWaitForScreens; - bool mScreensInitialized; - - static const struct wl_output_listener outputListener; - static void displayHandleGlobal(struct wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, void *data); - static void outputHandleGeometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height); -}; - -#endif // QWAYLANDEVENTTHREAD_H diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index aa72ad5..c7cd147 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -142,18 +142,12 @@ void QWaylandWindow::frameCallback(void *data, uint32_t time) { Q_UNUSED(time); QWaylandWindow *self = static_cast<QWaylandWindow*>(data); - if (self->mWaitingForFrameSync) { - self->mWaitingForFrameSync = false; - self->mFrameSyncWait.wakeAll(); - } + self->mWaitingForFrameSync = false; } void QWaylandWindow::waitForFrameSync() { - if (!mWaitingForFrameSync) { - return; - } - QMutex lock; - lock.lock(); - mFrameSyncWait.wait(&lock); + mDisplay->flushRequests(); + while (mWaitingForFrameSync) + mDisplay->readEvents(); } diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h index ad4bba4..35b82bd 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.h +++ b/src/plugins/platforms/wayland/qwaylandwindow.h @@ -44,7 +44,6 @@ #include <QtGui/QPlatformWindow> #include <QtCore/QWaitCondition> -#include <QtCore/QMutex> #include "qwaylanddisplay.h" diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 849299a..e5c866b 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -14,8 +14,7 @@ SOURCES = main.cpp \ qwaylanddisplay.cpp \ qwaylandwindow.cpp \ qwaylandscreen.cpp \ - qwaylandshmwindow.cpp \ - qwaylandeventthread.cpp + qwaylandshmwindow.cpp HEADERS = qwaylandintegration.h \ qwaylandcursor.h \ @@ -24,8 +23,7 @@ HEADERS = qwaylandintegration.h \ qwaylandscreen.h \ qwaylandshmsurface.h \ qwaylandbuffer.h \ - qwaylandshmwindow.h \ - qwaylandeventthread.h + qwaylandshmwindow.h INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND LIBS += $$QMAKE_LIBS_WAYLAND |