diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2011-01-27 10:15:34 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2011-01-27 10:15:34 (GMT) |
commit | aac8c2678867ae86af846a2644e37b3d1436406a (patch) | |
tree | 64a5eab52fbec59c7cdf04afe5d1e76a78ce5075 /src/plugins/platforms/wayland | |
parent | 39e6aa3f4434ab31d3d862574aa505b3f946ee9b (diff) | |
parent | b0390e68893dd04076434695be5e676b87bc067c (diff) | |
download | Qt-aac8c2678867ae86af846a2644e37b3d1436406a.zip Qt-aac8c2678867ae86af846a2644e37b3d1436406a.tar.gz Qt-aac8c2678867ae86af846a2644e37b3d1436406a.tar.bz2 |
Merge branch 'staging-master' of scm.dev.nokia.troll.no:qt/qt-lighthouse into master-integration
* 'staging-master' of scm.dev.nokia.troll.no:qt/qt-lighthouse: (69 commits)
Lighthouse: License headers to new files in testlite
Make sure we blit the fbo on flush in QGLWindowSurface
Lighthouse: Wayland. Make the wayland integration closer to Lighthosue
Lighthouse: Wayland, only make one fbo for the WaylandPaintDevice
Making clearer separation between responsibility of different classes
Make it possible to vertically mirror gl painting
Lighthouse:Wayland Moving some logic into files
Fix Wayland plugin to work with Wayland after some interfaces changed
Make QGLContext::fromPlatformGLContext show correct sharing
Remove Lighthouse specific code from QGLWindowSurface
Fix X11 clipboard bug.
Fix for uninitialized member in QWaylandCursor
wayland: use pkgconfig for libdrm in wayland.pro
wayland: remove non-public header from config.tests
wayland: fix SOURCES to point to wayland.cpp in config.tests
Wayland: request rbg and premultiplied argb visuals as needed
Wayland: clamp window resizes to screen size
Wayland: split GL code into separate files
Wayland: use correct viewport for swapBuffers and correct coords
Wayland: fix geometry of swapBuffers
...
Diffstat (limited to 'src/plugins/platforms/wayland')
21 files changed, 2670 insertions, 0 deletions
diff --git a/src/plugins/platforms/wayland/main.cpp b/src/plugins/platforms/wayland/main.cpp new file mode 100644 index 0000000..1bca661 --- /dev/null +++ b/src/plugins/platforms/wayland/main.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 <QtGui/QPlatformIntegrationPlugin> +#include "qwaylandintegration.h" + +QT_BEGIN_NAMESPACE + +class QWaylandIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QWaylandIntegrationPlugin::keys() const +{ + QStringList list; + list << "Wayland"; + list << "WaylandGL"; + return list; +} + +QPlatformIntegration *QWaylandIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "wayland") + return new QWaylandIntegration; + if (system.toLower() == "waylandgl") + return new QWaylandIntegration(true); + + return 0; +} + +Q_EXPORT_PLUGIN2(wayland, QWaylandIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.h b/src/plugins/platforms/wayland/qwaylandbuffer.h new file mode 100644 index 0000000..643e89c --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandbuffer.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 config.tests 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 QWAYLANDBUFFER_H +#define QWAYLANDBUFFER_H + +#include <QtCore/QSize> + +#include <wayland-client-protocol.h> + +class QWaylandBuffer { +public: + QWaylandBuffer() { } + virtual ~QWaylandBuffer() { } + wl_buffer *buffer() {return mBuffer;} + virtual QSize size() const = 0; + +protected: + struct wl_buffer *mBuffer; +}; + +#endif // QWAYLANDBUFFER_H diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp new file mode 100644 index 0000000..29c6abd --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** 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 QtOpenVG module 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 "qwaylandcursor.h" + +#include "qwaylanddisplay.h" +#include "qwaylandinputdevice.h" +#include "qwaylandshmsurface.h" +#include "qwaylandscreen.h" + +#include <QtGui/QImageReader> + +#define DATADIR "/home/jlind/install/share" + +static const struct pointer_image { + const char *filename; + int hotspot_x, hotspot_y; +} pointer_images[] = { + /* FIXME: Half of these are wrong... */ + /* Qt::ArrowCursor */ + { DATADIR "/wayland/left_ptr.png", 10, 5 }, + /* Qt::UpArrowCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::CrossCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::WaitCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::IBeamCursor */ + { DATADIR "/wayland/xterm.png", 15, 15 }, + /* Qt::SizeVerCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::SizeHorCursor */ + { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, + /* Qt::SizeBDiagCursor */ + { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, + /* Qt::SizeFDiagCursor */ + { DATADIR "/wayland/bottom_side.png", 16, 20 }, + /* Qt::SizeAllCursor */ + { DATADIR "/wayland/left_side.png", 10, 20 }, + /* Qt::BlankCursor */ + { DATADIR "/wayland/right_side.png", 30, 19 }, + /* Qt::SplitVCursor */ + { DATADIR "/wayland/sb_v_double_arrow.png", 15, 15 }, + /* Qt::SplitHCursor */ + { DATADIR "/wayland/sb_h_double_arrow.png", 15, 15 }, + /* Qt::PointingHandCursor */ + { DATADIR "/wayland/hand2.png", 14, 8 }, + /* Qt::ForbiddenCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::WhatsThisCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::BusyCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::OpenHandCursor */ + { DATADIR "/wayland/hand1.png", 18, 11 }, + /* Qt::ClosedHandCursor */ + { DATADIR "/wayland/grabbing.png", 20, 17 }, + /* Qt::DragCopyCursor */ + { DATADIR "/wayland/dnd-copy.png", 13, 13 }, + /* Qt::DragMoveCursor */ + { DATADIR "/wayland/dnd-move.png", 13, 13 }, + /* Qt::DragLinkCursor */ + { DATADIR "/wayland/dnd-link.png", 13, 13 }, +}; + +QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) + : QPlatformCursor(screen) + , mBuffer(0) + , mDisplay(screen->display()) +{ +} + +void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) +{ + const struct pointer_image *p; + + if (widget == NULL) + return; + + p = NULL; + + switch (cursor->shape()) { + case Qt::ArrowCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::UpArrowCursor: + case Qt::CrossCursor: + case Qt::WaitCursor: + break; + case Qt::IBeamCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::SizeVerCursor: /* 5 */ + case Qt::SizeHorCursor: + case Qt::SizeBDiagCursor: + case Qt::SizeFDiagCursor: + case Qt::SizeAllCursor: + case Qt::BlankCursor: /* 10 */ + break; + case Qt::SplitVCursor: + case Qt::SplitHCursor: + case Qt::PointingHandCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::ForbiddenCursor: + case Qt::WhatsThisCursor: /* 15 */ + case Qt::BusyCursor: + break; + case Qt::OpenHandCursor: + case Qt::ClosedHandCursor: + case Qt::DragCopyCursor: + case Qt::DragMoveCursor: /* 20 */ + case Qt::DragLinkCursor: + p = &pointer_images[cursor->shape()]; + break; + + default: + case Qt::BitmapCursor: + break; + } + + if (!p) { + p = &pointer_images[0]; + qWarning("unhandled cursor %d", cursor->shape()); + } + + QImageReader reader(p->filename); + + if (mBuffer == NULL || mBuffer->size() != reader.size()) { + if (mBuffer) + delete mBuffer; + + mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(), + QImage::Format_ARGB32); + } + + reader.read(mBuffer->image()); + + mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); +} + +void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y) +{ + /* Qt doesn't tell us which input device we should set the cursor + * for, so set it for all devices. */ + for (int i = 0; i < mInputDevices.count(); i++) { + QWaylandInputDevice *inputDevice = mInputDevices.at(i); + inputDevice->attach(buffer, x, y); + } +} diff --git a/src/plugins/platforms/wayland/qwaylandcursor.h b/src/plugins/platforms/wayland/qwaylandcursor.h new file mode 100644 index 0000000..19e6047 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandcursor.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 QtOpenVG module 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 QWAYLANDCURSOR_H +#define QWAYLANDCURSOR_H + +#include <QtGui/QPlatformCursor> + +class QWaylandShmBuffer; +class QWaylandDisplay; +class QWaylandScreen; + +class QWaylandCursor : QPlatformCursor { +public: + QWaylandCursor(QWaylandScreen *screen); + + void changeCursor(QCursor *cursor, QWidget *widget); + QWaylandShmBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +#endif // QWAYLANDCURSOR_H diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp new file mode 100644 index 0000000..70713ec --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** 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 "qwaylanddisplay.h" + +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" +#include "qwaylandcursor.h" +#include "qwaylandinputdevice.h" + +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +extern "C" { +#include <xf86drm.h> +} + +struct wl_surface *QWaylandDisplay::createSurface() +{ + return wl_compositor_create_surface(mCompositor); +} + +struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); +} + +struct wl_buffer *QWaylandDisplay::createDrmBuffer(int name, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_drm_create_buffer(mDrm, name, width, height, stride, visual); +} + +struct wl_visual *QWaylandDisplay::rgbVisual() +{ + return wl_display_get_rgb_visual(mDisplay); +} + +struct wl_visual *QWaylandDisplay::argbVisual() +{ + return wl_display_get_argb_visual(mDisplay); +} + +struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() +{ + return wl_display_get_premultiplied_argb_visual(mDisplay); +} + +void QWaylandDisplay::drmHandleDevice(void *data, + struct wl_drm *drm, const char *device) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + drm_magic_t magic; + + qwd->mDeviceName = strdup(device); + + qwd->mFd = open(qwd->mDeviceName, O_RDWR); + if (qwd->mFd < 0) { + qWarning("drm open failed: %m"); + return; + } + + if (drmGetMagic(qwd->mFd, &magic)) { + qWarning("DRI2: failed to get drm magic"); + return; + } + + wl_drm_authenticate(qwd->mDrm, magic); +} + +void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + EGLint major, minor; + const char *extensions; + + qwd->mEglDisplay = eglGetDRMDisplayMESA(qwd->mFd); + if (qwd->mEglDisplay == NULL) { + qWarning("failed to create display"); + return; + } + + if (!eglInitialize(qwd->mEglDisplay, &major, &minor)) { + qWarning("failed to initialize display"); + qwd->mEglDisplay = NULL; + return; + } + + extensions = eglQueryString(qwd->mEglDisplay, EGL_EXTENSIONS); + if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) { + qWarning("EGL_KHR_surfaceless_opengles2 not available"); + eglTerminate(qwd->mEglDisplay); + qwd->mEglDisplay = NULL; + return; + } +} + +const struct wl_drm_listener QWaylandDisplay::drmListener = { + QWaylandDisplay::drmHandleDevice, + QWaylandDisplay::drmHandleAuthenticated +}; + +void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height) +{ + Q_UNUSED(data); + Q_UNUSED(shell); + Q_UNUSED(time); + Q_UNUSED(edges); + QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); + + ww->configure(time, edges, 0, 0, width, height); +} + +const struct wl_shell_listener QWaylandDisplay::shellListener = { + QWaylandDisplay::shellHandleConfigure, +}; + +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + QWaylandDisplay *waylandDisplay = (QWaylandDisplay *) data; + + QRect outputRect = QRect(x, y, width, height); + waylandDisplay->createNewScreen(output, outputRect); +} + +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data) +{ + Q_UNUSED(version); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + if (strcmp(interface, "compositor") == 0) { + qwd->mCompositor = wl_compositor_create(display, id); + } else if (strcmp(interface, "drm") == 0) { + qwd->mDrm = wl_drm_create(display, id); + wl_drm_add_listener(qwd->mDrm, &drmListener, qwd); + } else if (strcmp(interface, "shm") == 0) { + qwd->mShm = wl_shm_create(display, id); + } else if (strcmp(interface, "shell") == 0) { + qwd->mShell = wl_shell_create(display, id); + wl_shell_add_listener(qwd->mShell, &shellListener, qwd); + } else if (strcmp(interface, "output") == 0) { + struct wl_output *output = wl_output_create(display, id); + wl_output_add_listener(output, &outputListener, qwd); + } else if (strcmp(interface, "input_device") == 0) { + QWaylandInputDevice *inputDevice = + new QWaylandInputDevice(display, id); + qwd->mInputDevices.append(inputDevice); + } +} + +static void roundtripCallback(void *data) +{ + bool *done = (bool *) data; + + *done = true; +} + +static void forceRoundtrip(struct wl_display *display) +{ + bool done; + + wl_display_sync_callback(display, roundtripCallback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + done = false; + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + +static const char *socket_name = NULL; + +void QWaylandDisplay::eventDispatcher(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} + +int +QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +{ + QWaylandDisplay *qwd = (QWaylandDisplay *) 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 (qwd->mWriteNotifier == NULL) + return 0; + + qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); + + return 0; +} + +void QWaylandDisplay::flushRequests(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); +} + +QWaylandDisplay::QWaylandDisplay(void) + : mWriteNotifier(0) +{ + mDisplay = wl_display_connect(socket_name); + if (mDisplay == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + return; + } + + wl_display_add_global_listener(mDisplay, + QWaylandDisplay::displayHandleGlobal, this); + + /* Process connection events. */ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + if (!mShm || !mDeviceName) + forceRoundtrip(mDisplay); + + /* Force a roundtrip to finish the drm authentication so we + * initialize EGL before proceeding */ + forceRoundtrip(mDisplay); + if (mEglDisplay == NULL) + qDebug("EGL not available"); + else + qDebug("EGL initialized"); + + int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); + mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(mReadNotifier, + SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); + connect(mWriteNotifier, + SIGNAL(activated(int)), this, SLOT(flushRequests())); + mWriteNotifier->setEnabled(false); +} + +QWaylandDisplay::~QWaylandDisplay(void) +{ + close(mFd); + wl_display_destroy(mDisplay); +} + +void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry) +{ + QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry); + mScreens.append(waylandScreen); +} + +void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) +{ + wl_display_sync_callback(mDisplay, func, data); +} + +void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data) +{ + wl_display_frame_callback(mDisplay, func, data); +} diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h new file mode 100644 index 0000000..f179713 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 QWAYLANDDISPLAY_H +#define QWAYLANDDISPLAY_H + +#include <QtCore/QObject> +#include <QtCore/QRect> + +#include <wayland-client.h> + +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +class QWaylandInputDevice; +class QSocketNotifier; +class QWaylandBuffer; +class QPlatformScreen; +class QWaylandScreen; + +class QWaylandDisplay : public QObject { + Q_OBJECT + +public: + QWaylandDisplay(void); + ~QWaylandDisplay(void); + + void createNewScreen(struct wl_output *output, QRect geometry); + QList<QPlatformScreen *> screens() const { return mScreens; } + struct wl_surface *createSurface(); + struct wl_buffer *createShmBuffer(int fd, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_buffer *createDrmBuffer(int name, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_visual *rgbVisual(); + struct wl_visual *argbVisual(); + struct wl_visual *argbPremultipliedVisual(); + EGLDisplay eglDisplay() { return mEglDisplay; } + + void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + + void syncCallback(wl_display_sync_func_t func, void *data); + void frameCallback(wl_display_frame_func_t func, void *data); + +public slots: + void eventDispatcher(void); + void flushRequests(void); + +private: + struct wl_display *mDisplay; + struct wl_compositor *mCompositor; + struct wl_drm *mDrm; + struct wl_shm *mShm; + struct wl_shell *mShell; + char *mDeviceName; + int mFd; + QList<QPlatformScreen *> mScreens; + QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; + QSocketNotifier *mWriteNotifier; + EGLDisplay mEglDisplay; + + static void displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data); + + static void drmHandleDevice(void *data, + struct wl_drm *drm, const char *device); + static void drmHandleAuthenticated(void *data, struct wl_drm *drm); + + static void outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height); + + static void shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height); + + static int sourceUpdate(uint32_t mask, void *data); + + static const struct wl_drm_listener drmListener; + static const struct wl_output_listener outputListener; + static const struct wl_shell_listener shellListener; +}; + +#endif // QWAYLANDDISPLAY_H diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp new file mode 100644 index 0000000..76c8c33 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module 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 "qwaylanddrmsurface.h" + +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" + +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> +#include <QtOpenGL/private/qgl_p.h> +#include <QtGui/private/qpaintengine_p.h> + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +/* + * Shared DRM surface for GL based drawing + */ +QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) + : mDisplay(display) + , mSize(size) +{ + struct wl_visual *visual; + EGLint name, stride; + EGLint imageAttribs[] = { + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_NONE + }; + + mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + glGenTextures(1, &mTexture); + glBindTexture(GL_TEXTURE_2D, mTexture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + + eglExportDRMImageMESA(mDisplay->eglDisplay(), + mImage, &name, NULL, &stride); + + switch (format) { + case QImage::Format_ARGB32: + visual = display->argbVisual(); + break; + case QImage::Format_ARGB32_Premultiplied: + visual = display->argbPremultipliedVisual(); + break; + default: + qDebug("unsupported buffer format %d requested\n", format); + visual = display->argbVisual(); + break; + } + + mBuffer = display->createDrmBuffer(name, size.width(), size.height(), + stride, visual); +} + +QWaylandDrmBuffer::~QWaylandDrmBuffer(void) +{ + glDeleteTextures(1, &mTexture); + eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); + wl_buffer_destroy(mBuffer); +} + +void QWaylandDrmBuffer::bindToCurrentFbo() +{ + Q_ASSERT(QPlatformGLContext::currentContext()); + glBindTexture(GL_TEXTURE_2D, mTexture); + glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, mTexture, 0); + QT_CHECK_GLERROR(); +} + +QWaylandPaintDevice::QWaylandPaintDevice(QWaylandDisplay *display, QWindowSurface *windowSurface, QPlatformGLContext *context) + : QGLPaintDevice() + , mDisplay(display) + , mPlatformGLContext(context) + , mWindowSurface(windowSurface) + , mBufferList(1) + , mCurrentPaintBuffer(0) + , mDepthStencil(0) +{ + for (int i = 0; i < mBufferList.size(); i++) { + mBufferList[i] = 0; + } + + mPlatformGLContext->makeCurrent(); + glGenFramebuffers(1, &m_thisFBO); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO); + + if (windowSurface->size().isValid()) + resize(windowSurface->size()); +} + +QWaylandPaintDevice::~QWaylandPaintDevice() +{ + for(int i = 0; i < mBufferList.size(); i++) { + delete mBufferList[i]; + } + glDeleteRenderbuffers(1,&mDepthStencil); + glDeleteFramebuffers(1,&m_thisFBO); +} + +QSize QWaylandPaintDevice::size() const +{ + return mSize; +} +QGLContext *QWaylandPaintDevice::context() const +{ + return QGLContext::fromPlatformGLContext(mPlatformGLContext); +} +QPaintEngine *QWaylandPaintDevice::paintEngine() const +{ + return qt_qgl_paint_engine(); +} + +void QWaylandPaintDevice::beginPaint() +{ + QGLPaintDevice::beginPaint(); + currentDrmBuffer()->bindToCurrentFbo(); +} + +bool QWaylandPaintDevice::isFlipped()const +{ + return true; +} + +void QWaylandPaintDevice::resize(const QSize &size) +{ + QImage::Format format = QPlatformScreen::platformScreenForWidget(mWindowSurface->window())->format(); + mPlatformGLContext->makeCurrent(); + mSize = size; + for (int i = 0; i < mBufferList.size(); i++) { + if (!mBufferList.at(i) || mBufferList.at(i)->size() != size) { + delete mBufferList[i]; + mBufferList[i] = new QWaylandDrmBuffer(mDisplay, size, format); + } + } + + glDeleteRenderbuffers(1,&mDepthStencil); + glGenRenderbuffers(1,&mDepthStencil); + glBindRenderbuffer(GL_RENDERBUFFER_EXT,mDepthStencil); + glRenderbufferStorage(GL_RENDERBUFFER_EXT, + GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + + switch(status) { + case GL_NO_ERROR: + case GL_FRAMEBUFFER_COMPLETE_EXT: + qDebug() << "fbo ok"; + break; + default: + qDebug() <<"QWaylandDrmBuffer error: "<< status; + break; + } + QT_CHECK_GLERROR(); +} + +QWaylandDrmBuffer *QWaylandPaintDevice::currentDrmBuffer() const +{ + return mBufferList[mCurrentPaintBuffer]; +} +QWaylandDrmBuffer *QWaylandPaintDevice::currentDrmBufferAndSwap() +{ + QWaylandDrmBuffer *currentDrmBuffer = mBufferList[mCurrentPaintBuffer]; + mCurrentPaintBuffer = (mCurrentPaintBuffer +1) % mBufferList.size(); + return currentDrmBuffer; +} + +QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window) + : QWindowSurface(window) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) + , mPaintDevice(new QWaylandPaintDevice(mDisplay, this,window->platformWindow()->glContext())) +{ + +} + +QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() +{ + delete mPaintDevice; +} + +void QWaylandDrmWindowSurface::beginPaint(const QRegion &) +{ + window()->platformWindow()->glContext()->makeCurrent(); +} + +QPaintDevice *QWaylandDrmWindowSurface::paintDevice() +{ + return mPaintDevice; +} + +void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(offset); + QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); + + ww->attach(mPaintDevice->currentDrmBufferAndSwap()); + + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); i++) { + QRect r = rects.at(i); + wl_surface_damage(ww->surface(), + r.x(), r.y(), r.width(), r.height()); + } +} + +void QWaylandDrmWindowSurface::resize(const QSize &requestedSize) +{ + QWindowSurface::resize(requestedSize); + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + + ww->glContext()->makeCurrent(); + + mPaintDevice->resize(requestedSize); + ww->attach(mPaintDevice->currentDrmBuffer()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/qwaylanddrmsurface.h new file mode 100644 index 0000000..eafea13 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 config.tests 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 QWAYLANDDRMSURFACE_H +#define QWAYLANDDRMSURFACE_H + +#include "qwaylanddisplay.h" +#include "qwaylandbuffer.h" + +#include <QtGui/private/qwindowsurface_p.h> +#include <QtCore/QVarLengthArray> +#include <QtOpenGL/private/qglpaintdevice_p.h> + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#define QT_RESET_GLERROR() \ +{ \ + while (glGetError() != GL_NO_ERROR) {} \ +} +#define QT_CHECK_GLERROR() \ +{ \ + GLenum err = glGetError(); \ + if (err != GL_NO_ERROR) { \ + qDebug("[%s line %d] GL Error: 0x%x", \ + __FILE__, __LINE__, (int)err); \ + } \ +} + +class QWaylandDrmBuffer : public QWaylandBuffer { +public: + QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandDrmBuffer(); + + void bindToCurrentFbo(); + QSize size() const { return mSize; } + +private: + EGLImageKHR mImage; + QWaylandDisplay *mDisplay; + QSize mSize; + GLuint mTexture; + +}; + +class QWaylandPaintDevice : public QGLPaintDevice +{ +public: + QWaylandPaintDevice(QWaylandDisplay *display, QWindowSurface *windowSurface, QPlatformGLContext *context); + ~QWaylandPaintDevice(); + + QSize size() const; + QGLContext *context() const; + QPaintEngine *paintEngine() const; + + void beginPaint(); + + bool isFlipped()const; + + void resize(const QSize &size); + + QWaylandDrmBuffer *currentDrmBuffer() const; + QWaylandDrmBuffer *currentDrmBufferAndSwap(); + +private: + QWaylandDisplay *mDisplay; + QPlatformGLContext *mPlatformGLContext; + QWindowSurface *mWindowSurface; + QVarLengthArray<QWaylandDrmBuffer *> mBufferList; + int mCurrentPaintBuffer; + GLuint mDepthStencil; + QSize mSize; + +}; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window); + ~QWaylandDrmWindowSurface(); + + void beginPaint(const QRegion &); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + + QWaylandDisplay *mDisplay; + QWaylandPaintDevice *mPaintDevice; +}; + +#endif // QWAYLANDDRMSURFACE_H diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/qwaylandglcontext.cpp new file mode 100644 index 0000000..4bf68c4 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandglcontext.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 "qwaylandglcontext.h" + +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylanddrmsurface.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +#include <unistd.h> +#include <fcntl.h> + +extern "C" { +#include <xf86drm.h> +} + +Q_GLOBAL_STATIC(QMutex,qt_defaultSharedContextMutex); + +EGLint QWaylandGLContext::contextAttibutes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE +}; + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , mFormat(format) + , mDisplay(wd) +{ + QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (qt_defaultSharedContextMutex()->tryLock()){ + createDefaultSharedContex(wd); + qt_defaultSharedContextMutex()->unlock(); + } else { + qt_defaultSharedContextMutex()->lock(); //wait to the the shared context is created + qt_defaultSharedContextMutex()->unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + mFormat.setSharedContext(sharePlatformContext); + EGLContext shareEGLContext = EGL_NO_CONTEXT; + if (sharePlatformContext) + shareEGLContext = static_cast<const QWaylandGLContext*>(sharePlatformContext)->mContext; + + eglBindAPI(EGL_OPENGL_ES_API); + mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + shareEGLContext, contextAttibutes); + + mFormat.setAccum(false); + mFormat.setAlphaBufferSize(8); + mFormat.setRedBufferSize(8); + mFormat.setGreenBufferSize(8); + mFormat.setBlueBufferSize(8); + mFormat.setDepth(false); +// mFormat.setDepthBufferSize(8); + mFormat.setStencil(false); +// mFormat.setStencilBufferSize(24); +// mFormat.setSampleBuffers(false); + +} + +QWaylandGLContext::QWaylandGLContext() + : QPlatformGLContext() + , mDisplay(0) + , mContext(EGL_NO_CONTEXT) +{ } + +QWaylandGLContext::~QWaylandGLContext() +{ + eglDestroyContext(mDisplay->eglDisplay(),mContext); +} + +void QWaylandGLContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, mContext); +} + +void QWaylandGLContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +void QWaylandGLContext::swapBuffers() +{ +} + +void *QWaylandGLContext::getProcAddress(const QString &string) +{ + return (void *) eglGetProcAddress(string.toLatin1().data()); +} + +void QWaylandGLContext::createDefaultSharedContex(QWaylandDisplay *display) +{ + QWaylandGLContext *defaultSharedContext = new QWaylandGLContext; + defaultSharedContext->mDisplay = display; + defaultSharedContext->mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + EGL_NO_CONTEXT, contextAttibutes); + QPlatformGLContext::setDefaultSharedContext(defaultSharedContext); +} + diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/qwaylandglcontext.h new file mode 100644 index 0000000..d9ba323 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandglcontext.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 QWAYLANDGLCONTEXT_H +#define QWAYLANDGLCONTEXT_H + +#include <QtGui/QPlatformGLContext> + +#include <QtCore/QMutex> +class QWaylandDisplay; +class QWaylandWindow; +class QWaylandDrmWindowSurface; + +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +class QWaylandGLContext : public QPlatformGLContext { +public: + QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); + ~QWaylandGLContext(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString&); + QPlatformWindowFormat platformWindowFormat() const { return mFormat; } + +private: + QPlatformWindowFormat mFormat; + QWaylandDisplay *mDisplay; + + static EGLint contextAttibutes[]; + EGLContext mContext; + + void createDefaultSharedContex(QWaylandDisplay *display); + QWaylandGLContext(); + +}; + + +#endif // QWAYLANDGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp new file mode 100644 index 0000000..03edc07 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** 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 "qwaylandinputdevice.h" + +#include "qwaylandintegration.h" +#include "qwaylandwindow.h" +#include "qwaylandbuffer.h" + +#include <QWindowSystemInterface> + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +#include <unistd.h> +#include <fcntl.h> +#include <X11/extensions/XKBcommon.h> +#include <X11/keysym.h> + +QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, + uint32_t id) + : mDisplay(display) + , mInputDevice(wl_input_device_create(display, id)) + , mPointerFocus(NULL) + , mKeyboardFocus(NULL) + , mButtons(0) +{ + struct xkb_rule_names names; + + wl_input_device_add_listener(mInputDevice, + &inputDeviceListener, + this); + wl_input_device_set_user_data(mInputDevice, this); + + names.rules = "evdev"; + names.model = "pc105"; + names.layout = "us"; + names.variant = ""; + names.options = ""; + + mXkb = xkb_compile_keymap_from_rules(&names); +} + +void QWaylandInputDevice::inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t surface_x, int32_t surface_y) +{ + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mPointerFocus; + + inputDevice->mSurfacePos = QPoint(surface_x, surface_y); + inputDevice->mGlobalPos = QPoint(x, y); + inputDevice->mTime = time; + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state) +{ + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mPointerFocus; + Qt::MouseButton qt_button; + + switch (button) { + case 272: + qt_button = Qt::LeftButton; + break; + case 273: + qt_button = Qt::RightButton; + break; + case 274: + qt_button = Qt::MiddleButton; + break; + default: + return; + } + + if (state) + inputDevice->mButtons |= qt_button; + else + inputDevice->mButtons &= ~qt_button; + + inputDevice->mTime = time; + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +static Qt::KeyboardModifiers translateModifiers(int s) +{ + const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK; + const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK; + + Qt::KeyboardModifiers ret = 0; + if (s & XKB_COMMON_SHIFT_MASK) + ret |= Qt::ShiftModifier; + if (s & XKB_COMMON_CONTROL_MASK) + ret |= Qt::ControlModifier; + if (s & qt_alt_mask) + ret |= Qt::AltModifier; + if (s & qt_meta_mask) + ret |= Qt::MetaModifier; + + return ret; +} + +static uint32_t translateKey(uint32_t sym, char *string, size_t size) +{ + Q_UNUSED(size); + string[0] = '\0'; + + switch (sym) { + case XK_Escape: return Qt::Key_Escape; + case XK_Tab: return Qt::Key_Tab; + case XK_ISO_Left_Tab: return Qt::Key_Backtab; + case XK_BackSpace: return Qt::Key_Backspace; + case XK_Return: return Qt::Key_Return; + case XK_Insert: return Qt::Key_Insert; + case XK_Delete: return Qt::Key_Delete; + case XK_Clear: return Qt::Key_Delete; + case XK_Pause: return Qt::Key_Pause; + case XK_Print: return Qt::Key_Print; + + case XK_Home: return Qt::Key_Home; + case XK_End: return Qt::Key_End; + case XK_Left: return Qt::Key_Left; + case XK_Up: return Qt::Key_Up; + case XK_Right: return Qt::Key_Right; + case XK_Down: return Qt::Key_Down; + case XK_Prior: return Qt::Key_PageUp; + case XK_Next: return Qt::Key_PageDown; + + case XK_Shift_L: return Qt::Key_Shift; + case XK_Shift_R: return Qt::Key_Shift; + case XK_Shift_Lock: return Qt::Key_Shift; + case XK_Control_L: return Qt::Key_Control; + case XK_Control_R: return Qt::Key_Control; + case XK_Meta_L: return Qt::Key_Meta; + case XK_Meta_R: return Qt::Key_Meta; + case XK_Alt_L: return Qt::Key_Alt; + case XK_Alt_R: return Qt::Key_Alt; + case XK_Caps_Lock: return Qt::Key_CapsLock; + case XK_Num_Lock: return Qt::Key_NumLock; + case XK_Scroll_Lock: return Qt::Key_ScrollLock; + case XK_Super_L: return Qt::Key_Super_L; + case XK_Super_R: return Qt::Key_Super_R; + case XK_Menu: return Qt::Key_Menu; + + default: + string[0] = sym; + string[1] = '\0'; + return toupper(sym); + } +} + +void QWaylandInputDevice::inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state) +{ + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mKeyboardFocus; + uint32_t code, sym, level; + Qt::KeyboardModifiers modifiers; + QEvent::Type type; + char s[2]; + + code = key + inputDevice->mXkb->min_key_code; + + level = 0; + if (inputDevice->mModifiers & Qt::ShiftModifier && + XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1) + level = 1; + + sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0); + + modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]); + + if (state) { + inputDevice->mModifiers |= modifiers; + type = QEvent::KeyPress; + } else { + inputDevice->mModifiers &= ~modifiers; + type = QEvent::KeyRelease; + } + + sym = translateKey(sym, s, sizeof s); + + qWarning("keycode %d, sym %d, string %d, modifiers 0x%x", + code, sym, s[0], (int) inputDevice->mModifiers); + + if (window) { + QWindowSystemInterface::handleKeyEvent(window->widget(), + time, type, sym, + inputDevice->mModifiers, + QString::fromLatin1(s)); + } +} + +void QWaylandInputDevice::inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + Q_UNUSED(input_device); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(sx); + Q_UNUSED(sy); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mPointerFocus) { + window = inputDevice->mPointerFocus; + QWindowSystemInterface::handleLeaveEvent(window->widget()); + inputDevice->mPointerFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + QWindowSystemInterface::handleEnterEvent(window->widget()); + inputDevice->mPointerFocus = window; + } + + inputDevice->mTime = time; +} + +void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys) +{ + Q_UNUSED(input_device); + Q_UNUSED(time); + Q_UNUSED(keys); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mKeyboardFocus) { + window = inputDevice->mKeyboardFocus; + inputDevice->mKeyboardFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + inputDevice->mKeyboardFocus = window; + } +} + +const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { + QWaylandInputDevice::inputHandleMotion, + QWaylandInputDevice::inputHandleButton, + QWaylandInputDevice::inputHandleKey, + QWaylandInputDevice::inputHandlePointerFocus, + QWaylandInputDevice::inputHandleKeyboardFocus, +}; + +void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) +{ + wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y); +} diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h new file mode 100644 index 0000000..2328db8 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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 QWAYLANDINPUTDEVICE_H +#define QWAYLANDINPUTDEVICE_H + +#include "qwaylandwindow.h" + +#include <QSocketNotifier> +#include <QObject> +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +#include <wayland-client.h> + +QT_BEGIN_NAMESPACE + +class QWaylandWindow; + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + void attach(QWaylandBuffer *buffer, int x, int y); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + QWaylandWindow *mPointerFocus; + QWaylandWindow *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + struct xkb_desc *mXkb; + Qt::KeyboardModifiers mModifiers; + uint32_t mTime; + + static void inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + static void inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); + static void inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state); + static void inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy); + static void inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp new file mode 100644 index 0000000..02bc680 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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 config.tests 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 "qwaylandintegration.h" + +#include "qwaylanddisplay.h" +#include "qwaylandshmsurface.h" +#include "qwaylanddrmsurface.h" +#include "qwaylandwindow.h" + +#include "qfontconfigdatabase.h" + +#include <QtGui/QWindowSystemInterface> +#include <QtGui/QPlatformCursor> +#include <QtGui/QPlatformWindowFormat> + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtOpenGL/private/qpixmapdata_gl_p.h> + +QWaylandIntegration::QWaylandIntegration(bool useOpenGL) + : mFontDb(new QFontconfigDatabase()) + , mDisplay(new QWaylandDisplay()) + , mUseOpenGL(useOpenGL) +{ +} + +QList<QPlatformScreen *> +QWaylandIntegration::screens() const +{ + return mDisplay->screens(); +} + +QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + if (mUseOpenGL) + return new QGLPixmapData(type); + return new QRasterPixmapData(type); +} + + + +QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QWaylandWindow(widget); +} + +QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + Q_UNUSED(winId); + + if (mUseOpenGL) + return new QWaylandDrmWindowSurface(widget); + return new QWaylandShmWindowSurface(widget); +} + +QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const +{ + return mFontDb; +} diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h new file mode 100644 index 0000000..d707612 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 QPLATFORMINTEGRATION_WAYLAND_H +#define QPLATFORMINTEGRATION_WAYLAND_H + +#include <QtGui/QPlatformIntegration> + +QT_BEGIN_NAMESPACE + +class QWaylandBuffer; +class QWaylandDisplay; + +class QWaylandIntegration : public QPlatformIntegration +{ +public: + QWaylandIntegration(bool useOpenGL = false); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const; + + QPlatformFontDatabase *fontDatabase() const; + +private: + QPlatformFontDatabase *mFontDb; + QWaylandDisplay *mDisplay; + bool mUseOpenGL; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp new file mode 100644 index 0000000..aa1083f --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 "qwaylandscreen.h" + +#include "qwaylanddisplay.h" +#include "qwaylandcursor.h" + +QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output *output, QRect geometry) + : QPlatformScreen() + , mWaylandDisplay(waylandDisplay) + , mOutput(output) + , mGeometry(geometry) + , mDepth(32) + , mFormat(QImage::Format_ARGB32_Premultiplied) + , mWaylandCursor(new QWaylandCursor(this)) +{ +} + +QWaylandScreen::~QWaylandScreen() +{ + delete mWaylandCursor; +} + +QWaylandDisplay * QWaylandScreen::display() const +{ + return mWaylandDisplay; +} + +QRect QWaylandScreen::geometry() const +{ + return mGeometry; +} + +int QWaylandScreen::depth() const +{ + return mDepth; +} + +QImage::Format QWaylandScreen::format() const +{ + return mFormat; +} + +QWaylandScreen * QWaylandScreen::waylandScreenFromWidget(QWidget *widget) +{ + QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWidget(widget); + return static_cast<QWaylandScreen *>(platformScreen); +} diff --git a/src/plugins/platforms/wayland/qwaylandscreen.h b/src/plugins/platforms/wayland/qwaylandscreen.h new file mode 100644 index 0000000..368859f --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandscreen.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 QWAYLANDSCREEN_H +#define QWAYLANDSCREEN_H + +#include <QtGui/QPlatformScreen> + +class QWaylandDisplay; +class QWaylandCursor; + +class QWaylandScreen : public QPlatformScreen +{ +public: + QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output *output, QRect geometry); + ~QWaylandScreen(); + + QWaylandDisplay *display() const; + + QRect geometry() const; + int depth() const; + QImage::Format format() const; + + static QWaylandScreen *waylandScreenFromWidget(QWidget *widget); + +private: + QWaylandDisplay *mWaylandDisplay; + struct wl_output *mOutput; + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + QWaylandCursor *mWaylandCursor; +}; + +#endif // QWAYLANDSCREEN_H diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp new file mode 100644 index 0000000..83bb993 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module 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 "qwaylandshmsurface.h" + +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) +{ + int stride = size.width() * 4; + int alloc = stride * size.height(); + char filename[] = "/tmp/wayland-shm-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) + qWarning("open %s failed: %s", filename, strerror(errno)); + if (ftruncate(fd, alloc) < 0) { + qWarning("ftruncate failed: %s", strerror(errno)); + close(fd); + return; + } + uchar *data = (uchar *) + mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (data == (uchar *) MAP_FAILED) { + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + close(fd); + return; + } + + mImage = QImage(data, size.width(), size.height(), stride, format); + mBuffer = display->createShmBuffer(fd, size.width(), size.height(), + stride, display->argbVisual()); + close(fd); +} + +QWaylandShmBuffer::~QWaylandShmBuffer(void) +{ + munmap((void *) mImage.constBits(), mImage.byteCount()); + wl_buffer_destroy(mBuffer); +} + +QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window) + : QWindowSurface(window) + , mBuffer(0) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) +{ +} + +QWaylandShmWindowSurface::~QWaylandShmWindowSurface() +{ +} + +QPaintDevice *QWaylandShmWindowSurface::paintDevice() +{ + return mBuffer->image(); +} + +void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QVector<QRect> rects = region.rects(); + const QRect *r; + int i; + + for (i = 0; i < rects.size(); i++) { + r = &rects.at(i); + wl_surface_damage(ww->surface(), + r->x(), r->y(), r->width(), r->height()); + } +} + +void QWaylandShmWindowSurface::resize(const QSize &size) +{ + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mBuffer != NULL && mBuffer->size() == size) + return; + + if (mBuffer != NULL) + delete mBuffer; + + mBuffer = new QWaylandShmBuffer(mDisplay, size, format); + + ww->attach(mBuffer); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h new file mode 100644 index 0000000..266b290 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module 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 QWINDOWSURFACE_WAYLAND_H +#define QWINDOWSURFACE_WAYLAND_H + +#include "qwaylandbuffer.h" +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QWaylandDisplay; + +class QWaylandShmBuffer : public QWaylandBuffer { +public: + QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandShmBuffer(); + QSize size() const { return mImage.size(); } + QImage *image() { return &mImage; } +private: + QImage mImage; +}; + +class QWaylandShmWindowSurface : public QWindowSurface +{ +public: + QWaylandShmWindowSurface(QWidget *window); + ~QWaylandShmWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QWaylandShmBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp new file mode 100644 index 0000000..a28bdfe --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** 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 config.tests 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 "qwaylandwindow.h" + +#include "qwaylanddisplay.h" +#include "qwaylandscreen.h" +#include "qwaylandglcontext.h" +#include "qwaylandbuffer.h" + +#include "qwaylanddrmsurface.h" + +#include <QtGui/QWidget> +#include <QtGui/QWindowSystemInterface> + +#include <QDebug> + +QWaylandWindow::QWaylandWindow(QWidget *window) + : QPlatformWindow(window) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) + , mGLContext(0) + , mBuffer(0) +{ + static WId id = 1; + mWindowId = id++; + + mSurface = mDisplay->createSurface(); +} + +QWaylandWindow::~QWaylandWindow() +{ + if (mGLContext) + delete mGLContext; +} + +WId QWaylandWindow::winId() const +{ + return mWindowId; +} + +void QWaylandWindow::setParent(const QPlatformWindow *parent) +{ + QWaylandWindow *wParent = (QWaylandWindow *)parent; + + mParentWindow = wParent; +} + +void QWaylandWindow::setVisible(bool visible) +{ + if (visible) { + wl_surface_set_user_data(mSurface, this); + wl_surface_map_toplevel(mSurface); + } else { + wl_surface_destroy(mSurface); + mSurface = NULL; + } +} + +void QWaylandWindow::attach(QWaylandBuffer *buffer) +{ + if (mSurface) { + wl_surface_attach(mSurface, buffer->buffer(),0,0); + } +} + +void QWaylandWindow::configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(time); + Q_UNUSED(edges); + QRect geometry = QRect(x, y, width, height); + + QWindowSystemInterface::handleGeometryChange(widget(), geometry); +} + +QPlatformGLContext *QWaylandWindow::glContext() const +{ + if (!mGLContext) { + QWaylandWindow *that = const_cast<QWaylandWindow *>(this); + that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat()); + } + + return mGLContext; +} diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h new file mode 100644 index 0000000..8b047d7 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindow.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 config.tests 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 QWAYLANDWINDOW_H +#define QWAYLANDWINDOW_H + +#include <QtGui/QPlatformWindow> + +#include <stdint.h> + +class QWaylandDisplay; +class QWaylandBuffer; + +class QWaylandWindow : public QPlatformWindow +{ +public: + QWaylandWindow(QWidget *window); + ~QWaylandWindow(); + struct wl_surface *surface() { return mSurface; } + + void setVisible(bool visible); + void configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, int32_t width, int32_t height); + WId winId() const; + void setParent(const QPlatformWindow *parent); + QPlatformGLContext *glContext() const; + void attach(QWaylandBuffer *buffer); + QWaylandBuffer *getBuffer(void) { return mBuffer; } + QWaylandWindow *getParentWindow(void) { return mParentWindow; } + +private: + struct wl_surface *mSurface; + QWaylandDisplay *mDisplay; + QPlatformGLContext *mGLContext; + WId mWindowId; + + QWaylandBuffer *mBuffer; + QWaylandWindow *mParentWindow; +}; + + +#endif // QWAYLANDWINDOW_H diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro new file mode 100644 index 0000000..8ba1408 --- /dev/null +++ b/src/plugins/platforms/wayland/wayland.pro @@ -0,0 +1,39 @@ +TARGET = qwayland +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qwaylandintegration.cpp \ + qwaylandshmsurface.cpp \ + qwaylanddrmsurface.cpp \ + qwaylandinputdevice.cpp \ + qwaylandglcontext.cpp \ + qwaylandcursor.cpp \ + qwaylanddisplay.cpp \ + qwaylandwindow.cpp \ + qwaylandscreen.cpp + +HEADERS = qwaylandintegration.h \ + qwaylandcursor.h \ + qwaylanddisplay.h \ + qwaylandwindow.h \ + qwaylandscreen.h \ + qwaylandglcontext.h \ + qwaylandshmsurface.h \ + qwaylanddrmsurface.h \ + qwaylandbuffer.h + +contains(QT_CONFIG, opengl) { + QT += opengl +} +LIBS += -lwayland-client -lxkbcommon -lEGL +unix { + CONFIG += link_pkgconfig + PKGCONFIG += libdrm +} + +include (../fontdatabases/fontconfig/fontconfig.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target |