diff options
author | Giulio Camuffo <giulio.camuffo@jollamobile.com> | 2014-03-25 14:19:55 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-04-29 10:09:31 +0200 |
commit | fc439e40e37f9c0b3108225f951fb19bb3abee80 (patch) | |
tree | 851bf52ee2004b3b201b5e86df7a4d4db7f79a2c /src/compositor/compositor_api | |
parent | c551e6df6c77f65a0db62b3ad4db539e86b75a30 (diff) |
Rework the way buffers are used and rendered
The current way buffers are handled is sub-optimal. They are hidden
inside QtWayland::Surface and the actual renderer, be it QtQuick or
anything else, cannot get a direct hold of them, nor it can directly
control when the underlying textures are created or deleted.
The main additions in this commit are the splitting of the QtQuick
code path and the new QWaylandBufferRef and QWaylandBufferAttacher
classes.
QWaylandBufferRef allows a renderer to retain a reference
to a wl_buffer even after the underlying Surface discarded it.
That allows the renderer to directly decide when to destroy the texture
of the buffer.
QWaylandBufferAttacher is a pure virtual class which must be implemented
by the renderer. Instances of it will be assigned to the QWaylandSurfaces,
created. Its attach() virtual method will then be called when a new buffer
is committed to the surface. The renderer can then choose to immediately
create a texture or wait for some later time. It is its responsibility to
create and destroy the GL texture, it will not happen automatically.
This functionality is implemented for QtQuick in the new QWaylandQuickCompositor
and QWaylandQuickSurface classes.
Change-Id: I674b4e5fb8c65c3b1c582e33ff3a0b0e45f2acc9
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Diffstat (limited to 'src/compositor/compositor_api')
-rw-r--r-- | src/compositor/compositor_api/compositor_api.pri | 15 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandbufferref.cpp | 131 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandbufferref.h | 87 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandcompositor.cpp | 37 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandcompositor.h | 5 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickcompositor.cpp | 102 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickcompositor.h | 64 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquicksurface.cpp | 241 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquicksurface.h | 91 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurface.cpp | 220 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurface.h | 57 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurface_p.h | 68 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurfaceitem.cpp | 173 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurfaceitem.h | 41 |
14 files changed, 995 insertions, 337 deletions
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index 87d28003c..8e7fd3ace 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -2,29 +2,34 @@ INCLUDEPATH += compositor_api HEADERS += \ compositor_api/qwaylandcompositor.h \ + compositor_api/qwaylandcompositor_p.h \ compositor_api/qwaylandsurface.h \ + compositor_api/qwaylandsurface_p.h \ compositor_api/qwaylandinput.h \ compositor_api/qwaylandinputpanel.h \ - compositor_api/qwaylanddrag.h + compositor_api/qwaylanddrag.h \ + compositor_api/qwaylandbufferref.h SOURCES += \ compositor_api/qwaylandcompositor.cpp \ compositor_api/qwaylandsurface.cpp \ compositor_api/qwaylandinput.cpp \ compositor_api/qwaylandinputpanel.cpp \ - compositor_api/qwaylanddrag.cpp + compositor_api/qwaylanddrag.cpp \ + compositor_api/qwaylandbufferref.cpp QT += core-private qtHaveModule(quick) { SOURCES += \ + compositor_api/qwaylandquickcompositor.cpp \ + compositor_api/qwaylandquicksurface.cpp \ compositor_api/qwaylandsurfaceitem.cpp HEADERS += \ + compositor_api/qwaylandquickcompositor.h \ + compositor_api/qwaylandquicksurface.h \ compositor_api/qwaylandsurfaceitem.h - DEFINES += QT_COMPOSITOR_QUICK - QT += qml quick - QT += quick-private gui-private } diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp new file mode 100644 index 000000000..67554c7cb --- /dev/null +++ b/src/compositor/compositor_api/qwaylandbufferref.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QAtomicInt> + +#include "qwaylandbufferref.h" +#include "wayland_wrapper/qwlsurfacebuffer_p.h" + +QT_BEGIN_NAMESPACE + +class QWaylandBufferRefPrivate +{ +public: + QtWayland::SurfaceBuffer *buffer; +}; + +QWaylandBufferRef::QWaylandBufferRef() + : d(new QWaylandBufferRefPrivate) +{ + d->buffer = 0; +} + +QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer) + : d(new QWaylandBufferRefPrivate) +{ + d->buffer = buffer; + if (buffer) + buffer->m_refCount.ref(); +} + +QWaylandBufferRef::QWaylandBufferRef(const QWaylandBufferRef &ref) + : d(new QWaylandBufferRefPrivate) +{ + d->buffer = 0; + *this = ref; +} + +QWaylandBufferRef::~QWaylandBufferRef() +{ + if (d->buffer && !d->buffer->m_refCount.deref()) + d->buffer->disown(); + delete d; +} + +QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) +{ + if (d->buffer && !d->buffer->m_refCount.deref()) + d->buffer->disown(); + + d->buffer = ref.d->buffer; + if (d->buffer) + d->buffer->m_refCount.ref(); + + return *this; +} + +QWaylandBufferRef::operator bool() const +{ + return d->buffer && d->buffer->waylandBufferHandle(); +} + +bool QWaylandBufferRef::isShm() const +{ + return d->buffer->isShmBuffer(); +} + +QImage QWaylandBufferRef::image() const +{ + if (d->buffer->isShmBuffer()) + return d->buffer->image(); + return QImage(); +} + +#ifdef QT_COMPOSITOR_WAYLAND_GL + +GLuint QWaylandBufferRef::createTexture() +{ + if (!d->buffer->isShmBuffer() && !d->buffer->textureCreated()) { + d->buffer->createTexture(); + } + return d->buffer->texture(); +} + +void QWaylandBufferRef::destroyTexture() +{ + if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) { + d->buffer->destroyTexture(); + } +} +#endif + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h new file mode 100644 index 000000000..0d1573bbb --- /dev/null +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDBUFFERREF_H +#define QWAYLANDBUFFERREF_H + +#ifdef QT_COMPOSITOR_WAYLAND_GL +#include <QtGui/qopengl.h> +#endif + +#include <QtCompositor/qwaylandexport.h> + +QT_BEGIN_NAMESPACE + +namespace QtWayland +{ + class SurfaceBuffer; +} + +class Q_COMPOSITOR_EXPORT QWaylandBufferRef +{ +public: + QWaylandBufferRef(); + explicit QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer); + QWaylandBufferRef(const QWaylandBufferRef &ref); + ~QWaylandBufferRef(); + + QWaylandBufferRef &operator=(const QWaylandBufferRef &ref); + operator bool() const; + bool isShm() const; + + QImage image() const; +#ifdef QT_COMPOSITOR_WAYLAND_GL + /** + * There must be a GL context bound when calling this function. + * It is responsibility of the caller to call destroyTexture() later. + */ + GLuint createTexture(); + void destroyTexture(); +#endif + +private: + class QWaylandBufferRefPrivate *const d; + friend class QWaylandBufferRefPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 342dce510..2135a0e94 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -55,33 +55,26 @@ #include <QDebug> -#ifdef QT_COMPOSITOR_QUICK -#include "qwaylandsurfaceitem.h" -#endif - QT_BEGIN_NAMESPACE QWaylandCompositor::QWaylandCompositor(QWindow *window, const char *socketName, ExtensionFlags extensions) - : m_compositor(0) + : m_compositor(new QtWayland::Compositor(this, extensions)) , m_toplevel_window(window) - , m_socket_name(socketName) { - QStringList arguments = QCoreApplication::instance()->arguments(); + m_compositor->m_socket_name = socketName; + m_compositor->init(); - int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name")); - if (socketArg != -1 && socketArg + 1 < arguments.size()) - m_socket_name = arguments.at(socketArg + 1).toLocal8Bit(); - - m_compositor = new QtWayland::Compositor(this, extensions); -#ifdef QT_COMPOSITOR_QUICK - qmlRegisterType<QWaylandSurfaceItem>("WaylandCompositor", 1, 0, "WaylandSurfaceItem"); - qmlRegisterType<QWaylandSurface>("WaylandCompositor", 1, 0, "WaylandSurface"); -#else - qRegisterMetaType<QWaylandSurface*>("WaylandSurface*"); +#if !defined(QT_NO_DEBUG) && !defined(QT_WAYLAND_NO_CLEANUP_WARNING) + qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually"); #endif - m_compositor->initializeHardwareIntegration(); - m_compositor->initializeExtensions(); - m_compositor->initializeDefaultInputDevice(); +} + +QWaylandCompositor::QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr) + : m_compositor(dptr) + , m_toplevel_window(window) +{ + m_compositor->m_socket_name = socketName; + m_compositor->init(); } QWaylandCompositor::~QWaylandCompositor() @@ -213,9 +206,9 @@ void QWaylandCompositor::setClientFullScreenHint(bool value) const char *QWaylandCompositor::socketName() const { - if (m_socket_name.isEmpty()) + if (m_compositor->m_socket_name.isEmpty()) return 0; - return m_socket_name.constData(); + return m_compositor->m_socket_name.constData(); } /*! diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index 9009f4caa..85f10b281 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -141,13 +141,14 @@ public: void configureTouchExtension(TouchExtensionFlags flags); protected: + QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr); virtual void retainedSelectionReceived(QMimeData *mimeData); -private: friend class QtWayland::Compositor; QtWayland::Compositor *m_compositor; + +private: QWindow *m_toplevel_window; - QByteArray m_socket_name; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandCompositor::ExtensionFlags) diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp new file mode 100644 index 000000000..bc475f1c5 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QQuickWindow> + +#include <QtCompositor/private/qwlcompositor_p.h> + +#include "qwaylandquickcompositor.h" +#include "qwaylandquicksurface.h" +#include "qwaylandsurfaceitem.h" + +QT_BEGIN_NAMESPACE + +class QWaylandQuickCompositorPrivate : public QtWayland::Compositor +{ +public: + QWaylandQuickCompositorPrivate(QWaylandQuickCompositor *compositor, QWaylandCompositor::ExtensionFlags extensions) + : QtWayland::Compositor(compositor, extensions) + , updateScheduled(false) + { + } + + void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE + { + QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, static_cast<QWaylandQuickCompositor *>(m_qt_compositor)); + m_surfaces << surface->handle(); + //BUG: This may not be an on-screen window surface though + m_qt_compositor->surfaceCreated(surface); + } + + void updateStarted() + { + updateScheduled = false; + m_qt_compositor->frameStarted(); + m_qt_compositor->cleanupGraphicsResources(); + } + + bool updateScheduled; +}; + + +QWaylandQuickCompositor::QWaylandQuickCompositor(QQuickWindow *window, const char *socketName, ExtensionFlags extensions) + : QWaylandCompositor(window, socketName, new QWaylandQuickCompositorPrivate(this, extensions)) +{ + window->connect(window, &QQuickWindow::beforeSynchronizing, d_ptr(), &QWaylandQuickCompositorPrivate::updateStarted, Qt::DirectConnection); + + qmlRegisterType<QWaylandSurfaceItem>("QtCompositor", 1, 0, "WaylandSurfaceItem"); + qmlRegisterUncreatableType<QWaylandQuickSurface>("QtCompositor", 1, 0, "WaylandQuickSurface", QObject::tr("Cannot create instance of WaylandQuickSurface")); +} + +QWaylandQuickCompositorPrivate *QWaylandQuickCompositor::d_ptr() +{ + return static_cast<QWaylandQuickCompositorPrivate *>(m_compositor); +} + +void QWaylandQuickCompositor::update() +{ + if (!d_ptr()->updateScheduled) { + static_cast<QQuickWindow *>(window())->update(); + d_ptr()->updateScheduled = true; + } +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.h b/src/compositor/compositor_api/qwaylandquickcompositor.h new file mode 100644 index 000000000..c87585221 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickcompositor.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDQUICKCOMPOSITOR_H +#define QWAYLANDQUICKCOMPOSITOR_H + +#include <QtCompositor/qwaylandcompositor.h> + +QT_BEGIN_NAMESPACE + +class QQuickWindow; +class QWaylandQuickCompositorPrivate; + +class Q_COMPOSITOR_EXPORT QWaylandQuickCompositor : public QWaylandCompositor +{ +public: + QWaylandQuickCompositor(QQuickWindow *window = 0, const char *socketName = 0, QWaylandCompositor::ExtensionFlags extensions = DefaultExtensions); + + void update(); + +private: + friend class QWaylandQuickCompositorPrivate; + QWaylandQuickCompositorPrivate *d_ptr(); +}; + +#endif diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp new file mode 100644 index 000000000..e4a5f7732 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QSGTexture> +#include <QOpenGLTexture> +#include <QQuickWindow> +#include <QDebug> +#include <QQmlPropertyMap> + +#include "qwaylandquicksurface.h" +#include "qwaylandquickcompositor.h" +#include "qwaylandsurfaceitem.h" +#include <QtCompositor/qwaylandbufferref.h> +#include <QtCompositor/private/qwaylandsurface_p.h> + +QT_BEGIN_NAMESPACE + +class BufferAttacher : public QWaylandBufferAttacher +{ +public: + BufferAttacher() + : surface(0) + , texture(0) + , update(false) + { + + } + + ~BufferAttacher() + { + if (texture) + texture->deleteLater(); + bufferRef = QWaylandBufferRef(); + nextBuffer = QWaylandBufferRef(); + } + + void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE + { + nextBuffer = ref; + update = true; + } + + void createTexture() + { + if (bufferRef) + bufferRef.destroyTexture(); + bufferRef = nextBuffer; + + QQuickWindow *window = static_cast<QQuickWindow *>(surface->compositor()->window()); + // If the next buffer is NULL do not delete the current texture. If the client called + // attach(0) the surface is going to be unmapped anyway, if instead the client attached + // a valid buffer but died before we got here we want to keep the old buffer around + // in case some destroy animation is run. + if (bufferRef) { + delete texture; + + if (bufferRef.isShm()) { + texture = window->createTextureFromImage(bufferRef.image()); + } else { + QQuickWindow::CreateTextureOptions opt = 0; + if (surface->useTextureAlpha()) { + opt |= QQuickWindow::TextureHasAlphaChannel; + } + texture = window->createTextureFromId(bufferRef.createTexture(), surface->size(), opt); + } + texture->bind(); + } + + update = false; + } + + void invalidateTexture() + { + delete texture; + texture = 0; + } + + QWaylandQuickSurface *surface; + QWaylandBufferRef bufferRef; + QWaylandBufferRef nextBuffer; + QSGTexture *texture; + bool update; +}; + + +class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate +{ +public: + QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf) + : QWaylandSurfacePrivate(client, id, c, surf) + , buffer(new BufferAttacher) + , compositor(c) + , useTextureAlpha(true) + , windowPropertyMap(new QQmlPropertyMap) + , clientRenderingEnabled(true) + { + + } + + ~QWaylandQuickSurfacePrivate() + { + windowPropertyMap->deleteLater(); + // buffer is deleted automatically by ~Surface(), since it is the assigned attacher + } + + void surface_commit(Resource *resource) Q_DECL_OVERRIDE + { + if (m_pending.newlyAttached) { + buffer->update = true; + } + QWaylandSurfacePrivate::surface_commit(resource); + + compositor->update(); + } + + BufferAttacher *buffer; + QWaylandQuickCompositor *compositor; + bool useTextureAlpha; + QQmlPropertyMap *windowPropertyMap; + bool clientRenderingEnabled; +}; + +QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor) + : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, compositor, this)) +{ + Q_D(QWaylandQuickSurface); + d->buffer->surface = this; + setBufferAttacher(d->buffer); + + QQuickWindow *window = static_cast<QQuickWindow *>(compositor->window()); + connect(window, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickSurface::updateTexture, Qt::DirectConnection); + connect(window, &QQuickWindow::sceneGraphInvalidated, this, &QWaylandQuickSurface::invalidateTexture, Qt::DirectConnection); + connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert); + connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty); + +} + +QWaylandQuickSurface::~QWaylandQuickSurface() +{ + +} + +QSGTexture *QWaylandQuickSurface::texture() const +{ + Q_D(const QWaylandQuickSurface); + return d->buffer->texture; +} + +bool QWaylandQuickSurface::useTextureAlpha() const +{ + Q_D(const QWaylandQuickSurface); + return d->useTextureAlpha; +} + +void QWaylandQuickSurface::setUseTextureAlpha(bool useTextureAlpha) +{ + Q_D(QWaylandQuickSurface); + if (d->useTextureAlpha != useTextureAlpha) { + d->useTextureAlpha = useTextureAlpha; + emit useTextureAlphaChanged(); + emit configure(); + } +} + +QObject *QWaylandQuickSurface::windowPropertyMap() const +{ + Q_D(const QWaylandQuickSurface); + return d->windowPropertyMap; +} + + +void QWaylandQuickSurface::updateTexture() +{ + Q_D(QWaylandQuickSurface); + if (d->buffer->update) + d->buffer->createTexture(); +} + +void QWaylandQuickSurface::invalidateTexture() +{ + Q_D(QWaylandQuickSurface); + d->buffer->invalidateTexture(); +} + +bool QWaylandQuickSurface::clientRenderingEnabled() const +{ + Q_D(const QWaylandQuickSurface); + return d->clientRenderingEnabled; +} + +void QWaylandQuickSurface::setClientRenderingEnabled(bool enabled) +{ + Q_D(QWaylandQuickSurface); + if (d->clientRenderingEnabled != enabled) { + d->clientRenderingEnabled = enabled; + + sendOnScreenVisibilityChange(enabled); + + emit clientRenderingEnabledChanged(); + } +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h new file mode 100644 index 000000000..6c464ecd7 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWAYLANDSURFACE_H +#define QQUICKWAYLANDSURFACE_H + +#include <QSGTexture> +#include <QSGTextureProvider> + +#include "qwaylandsurface.h" + +struct wl_client; + +QT_BEGIN_NAMESPACE + +class QWaylandSurfaceItem; +class QWaylandQuickSurfacePrivate; +class QWaylandQuickCompositor; + +class Q_COMPOSITOR_EXPORT QWaylandQuickSurface : public QWaylandSurface +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandQuickSurface) + Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged) + Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) + Q_PROPERTY(QObject *windowProperties READ windowPropertyMap CONSTANT) +public: + QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor); + ~QWaylandQuickSurface(); + + QSGTexture *texture() const; + + bool useTextureAlpha() const; + void setUseTextureAlpha(bool useTextureAlpha); + + bool clientRenderingEnabled() const; + void setClientRenderingEnabled(bool enabled); + + QObject *windowPropertyMap() const; + +signals: + void useTextureAlphaChanged(); + void clientRenderingEnabledChanged(); + +private: + void updateTexture(); + void invalidateTexture(); + +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 2b7d713c8..5fd7fabe9 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -53,74 +53,51 @@ #include "qwaylandcompositor.h" #include "waylandwindowmanagerintegration.h" +#include "qwaylandsurface_p.h" +#include "qwaylandbufferref.h" #include <QtGui/QGuiApplication> #include <QtGui/QScreen> -#ifdef QT_COMPOSITOR_QUICK -#include "qwaylandsurfaceitem.h" -#include <QtQml/QQmlPropertyMap> -#endif - QT_BEGIN_NAMESPACE -class QWaylandSurfacePrivate : public QObjectPrivate -{ -public: - QWaylandSurfacePrivate(QtWayland::Surface *srfc) - : surface(srfc) -#ifdef QT_COMPOSITOR_QUICK - , surface_item(0) - , windowPropertyMap(new QQmlPropertyMap) -#endif - {} - - ~QWaylandSurfacePrivate() - { -#ifdef QT_COMPOSITOR_QUICK - if (surface_item) - surface_item->setSurface(0); - if (windowPropertyMap) - windowPropertyMap->deleteLater(); -#endif - } +QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *client, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface) + : QtWayland::Surface(client, id, compositor, surface) + , closing(false) + , refCount(1) +{} - QtWayland::Surface *surface; -#ifdef QT_COMPOSITOR_QUICK - QWaylandSurfaceItem *surface_item; - QQmlPropertyMap *windowPropertyMap; -#endif -}; -QWaylandSurface::QWaylandSurface(QtWayland::Surface *surface) - : QObject(*new QWaylandSurfacePrivate(surface)) + +QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor) + : QObject(*new QWaylandSurfacePrivate(client, id, compositor, this)) { -#ifdef QT_COMPOSITOR_QUICK - Q_D(QWaylandSurface); - connect(this, &QWaylandSurface::windowPropertyChanged, - d->windowPropertyMap, &QQmlPropertyMap::insert); - connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, - this, &QWaylandSurface::setWindowProperty); -#endif + } -void QWaylandSurface::swapBuffers() +QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate *dptr) + : QObject(*dptr) { - Q_D(const QWaylandSurface); - d->surface->swapBuffers(); + +} + +QWaylandSurface::~QWaylandSurface() +{ + Q_D(QWaylandSurface); + delete d->m_attacher; } WaylandClient *QWaylandSurface::client() const { Q_D(const QWaylandSurface); - return d->surface->resource()->client(); + return d->resource()->client(); } QWaylandSurface *QWaylandSurface::parentSurface() const { Q_D(const QWaylandSurface); - if (d->surface->subSurface() && d->surface->subSurface()->parent()) { - return d->surface->subSurface()->parent()->waylandSurface(); + if (d->subSurface() && d->subSurface()->parent()) { + return d->subSurface()->parent()->waylandSurface(); } return 0; } @@ -128,8 +105,8 @@ QWaylandSurface *QWaylandSurface::parentSurface() const QLinkedList<QWaylandSurface *> QWaylandSurface::subSurfaces() const { Q_D(const QWaylandSurface); - if (d->surface->subSurface()) { - return d->surface->subSurface()->subSurfaces(); + if (d->subSurface()) { + return d->subSurface()->subSurfaces(); } return QLinkedList<QWaylandSurface *>(); } @@ -137,13 +114,13 @@ QLinkedList<QWaylandSurface *> QWaylandSurface::subSurfaces() const QWaylandSurface::Type QWaylandSurface::type() const { Q_D(const QWaylandSurface); - return d->surface->type(); + return d->type(); } bool QWaylandSurface::isYInverted() const { Q_D(const QWaylandSurface); - return d->surface->isYInverted(); + return d->isYInverted(); } bool QWaylandSurface::visible() const @@ -154,110 +131,70 @@ bool QWaylandSurface::visible() const bool QWaylandSurface::isMapped() const { Q_D(const QWaylandSurface); - return d->surface->mapped(); + return d->mapped(); } QPointF QWaylandSurface::pos() const { Q_D(const QWaylandSurface); - return d->surface->pos(); + return d->pos(); } void QWaylandSurface::setPos(const QPointF &pos) { Q_D(QWaylandSurface); - d->surface->setPos(pos); + d->setPos(pos); } QSize QWaylandSurface::size() const { Q_D(const QWaylandSurface); - return d->surface->size(); + return d->size(); } void QWaylandSurface::requestSize(const QSize &size) { Q_D(QWaylandSurface); - if (d->surface->shellSurface()) - d->surface->shellSurface()->sendConfigure(WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, size.width(), size.height()); + if (d->shellSurface()) + d->shellSurface()->sendConfigure(WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, size.width(), size.height()); } Qt::ScreenOrientations QWaylandSurface::orientationUpdateMask() const { Q_D(const QWaylandSurface); - return d->surface->compositor()->orientationUpdateMaskForClient(static_cast<wl_client *>(client())); + return d->compositor()->orientationUpdateMaskForClient(static_cast<wl_client *>(client())); } Qt::ScreenOrientation QWaylandSurface::contentOrientation() const { Q_D(const QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return Qt::PrimaryOrientation; - return d->surface->extendedSurface()->contentOrientation(); + return d->extendedSurface()->contentOrientation(); } QWaylandSurface::WindowFlags QWaylandSurface::windowFlags() const { Q_D(const QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return QWaylandSurface::WindowFlags(0); - return d->surface->extendedSurface()->windowFlags(); + return d->extendedSurface()->windowFlags(); } QWaylandSurface::WindowType QWaylandSurface::windowType() const { Q_D(const QWaylandSurface); - if (d->surface->shellSurface()) - return d->surface->shellSurface()->windowType(); + if (d->shellSurface()) + return d->shellSurface()->windowType(); return QWaylandSurface::None; } -QImage QWaylandSurface::image() const -{ - Q_D(const QWaylandSurface); - return d->surface->image(); -} - -#ifdef QT_COMPOSITOR_WAYLAND_GL -GLuint QWaylandSurface::texture() const -{ - Q_D(const QWaylandSurface); - return d->surface->textureId(); -} -#else //QT_COMPOSITOR_WAYLAND_GL -uint QWaylandSurface::texture() const -{ - return 0; -} -#endif - -QtWayland::Surface * QWaylandSurface::handle() const -{ - Q_D(const QWaylandSurface); - return d->surface; -} - -#ifdef QT_COMPOSITOR_QUICK -QWaylandSurfaceItem *QWaylandSurface::surfaceItem() const -{ - Q_D(const QWaylandSurface); - return d->surface_item; -} - -void QWaylandSurface::setSurfaceItem(QWaylandSurfaceItem *surfaceItem) +QtWayland::Surface * QWaylandSurface::handle() { Q_D(QWaylandSurface); - d->surface_item = surfaceItem; + return d; } -QObject *QWaylandSurface::windowPropertyMap() const -{ - Q_D(const QWaylandSurface); - return d->windowPropertyMap; -} - -#endif //QT_COMPOSITOR_QUICK - qint64 QWaylandSurface::processId() const { struct wl_client *client = static_cast<struct wl_client *>(this->client()); @@ -269,19 +206,19 @@ qint64 QWaylandSurface::processId() const QVariantMap QWaylandSurface::windowProperties() const { Q_D(const QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return QVariantMap(); - return d->surface->extendedSurface()->windowProperties(); + return d->extendedSurface()->windowProperties(); } void QWaylandSurface::setWindowProperty(const QString &name, const QVariant &value) { Q_D(QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return; - d->surface->extendedSurface()->setWindowProperty(name, value); + d->extendedSurface()->setWindowProperty(name, value); } QPointF QWaylandSurface::mapToParent(const QPointF &pos) const @@ -307,22 +244,22 @@ QPointF QWaylandSurface::mapTo(QWaylandSurface *parent, const QPointF &pos) cons QWaylandCompositor *QWaylandSurface::compositor() const { Q_D(const QWaylandSurface); - return d->surface->compositor()->waylandCompositor(); + return d->compositor()->waylandCompositor(); } QWaylandSurface *QWaylandSurface::transientParent() const { Q_D(const QWaylandSurface); - if (d->surface->shellSurface() && d->surface->shellSurface()->transientParent()) - return d->surface->shellSurface()->transientParent()->surface()->waylandSurface(); + if (d->shellSurface() && d->shellSurface()->transientParent()) + return d->shellSurface()->transientParent()->surface()->waylandSurface(); return 0; } QWindow::Visibility QWaylandSurface::visibility() const { Q_D(const QWaylandSurface); - if (d->surface->extendedSurface()) - return d->surface->extendedSurface()->visibility(); + if (d->extendedSurface()) + return d->extendedSurface()->visibility(); return QWindow::AutomaticVisibility; } @@ -330,8 +267,8 @@ QWindow::Visibility QWaylandSurface::visibility() const void QWaylandSurface::setVisibility(QWindow::Visibility visibility) { Q_D(QWaylandSurface); - if (d->surface->extendedSurface()) - d->surface->extendedSurface()->setVisibility(visibility); + if (d->extendedSurface()) + d->extendedSurface()->setVisibility(visibility); } void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) @@ -342,19 +279,19 @@ void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) QString QWaylandSurface::className() const { Q_D(const QWaylandSurface); - return d->surface->className(); + return d->className(); } QString QWaylandSurface::title() const { Q_D(const QWaylandSurface); - return d->surface->title(); + return d->title(); } bool QWaylandSurface::hasShellSurface() const { Q_D(const QWaylandSurface); - if (d->surface->shellSurface()) + if (d->shellSurface()) return true; return false; @@ -364,7 +301,7 @@ bool QWaylandSurface::hasInputPanelSurface() const { Q_D(const QWaylandSurface); - return d->surface->inputPanelSurface() != 0; + return d->inputPanelSurface() != 0; } /*! @@ -373,14 +310,21 @@ bool QWaylandSurface::hasInputPanelSurface() const bool QWaylandSurface::transientInactive() const { Q_D(const QWaylandSurface); - return d->surface->transientInactive(); + return d->transientInactive(); +} + +void QWaylandSurface::destroy() +{ + Q_D(QWaylandSurface); + if (--d->refCount == 0) + compositor()->handle()->destroySurface(d); } void QWaylandSurface::destroySurface() { Q_D(QWaylandSurface); - if (d->surface->extendedSurface()) { - d->surface->extendedSurface()->send_close(); + if (d->extendedSurface()) { + d->extendedSurface()->send_close(); } else { destroySurfaceByForce(); } @@ -389,15 +333,15 @@ void QWaylandSurface::destroySurface() void QWaylandSurface::destroySurfaceByForce() { Q_D(QWaylandSurface); - wl_resource *surface_resource = d->surface->resource()->handle; + wl_resource *surface_resource = d->resource()->handle; wl_resource_destroy(surface_resource); } void QWaylandSurface::ping() { Q_D(QWaylandSurface); - if (d->surface->shellSurface()) - d->surface->shellSurface()->ping(); + if (d->shellSurface()) + d->shellSurface()->ping(); } /*! @@ -408,14 +352,32 @@ void QWaylandSurface::ping() void QWaylandSurface::updateSelection() { Q_D(QWaylandSurface); - const QtWayland::InputDevice *inputDevice = d->surface->compositor()->defaultInputDevice(); + const QtWayland::InputDevice *inputDevice = d->compositor()->defaultInputDevice(); if (inputDevice) { const QtWayland::DataDevice *dataDevice = inputDevice->dataDevice(); if (dataDevice) { - d->surface->compositor()->dataDeviceManager()->offerRetainedSelection( - dataDevice->resourceMap().value(d->surface->resource()->client())->handle); + d->compositor()->dataDeviceManager()->offerRetainedSelection( + dataDevice->resourceMap().value(d->resource()->client())->handle); } } } +void QWaylandSurface::ref() +{ + Q_D(QWaylandSurface); + ++d->refCount; +} + +void QWaylandSurface::setBufferAttacher(QWaylandBufferAttacher *attacher) +{ + Q_D(QWaylandSurface); + d->m_attacher = attacher; +} + +QWaylandBufferAttacher *QWaylandSurface::bufferAttacher() const +{ + Q_D(const QWaylandSurface); + return d->m_attacher; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index 2f7b70ce8..22deee5ae 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -48,19 +48,14 @@ #include <QtGui/QWindow> #include <QtCore/QVariantMap> -#ifdef QT_COMPOSITOR_WAYLAND_GL -#include <QtGui/qopengl.h> -#endif +struct wl_client; QT_BEGIN_NAMESPACE class QTouchEvent; class QWaylandSurfacePrivate; class QWaylandCompositor; - -#ifdef QT_COMPOSITOR_QUICK -class QWaylandSurfaceItem; -#endif +class QWaylandBufferRef; namespace QtWayland { class Surface; @@ -68,6 +63,17 @@ class SurfacePrivate; class ExtendedSurface; } +class Q_COMPOSITOR_EXPORT QWaylandBufferAttacher +{ +public: + virtual ~QWaylandBufferAttacher() {} + +protected: + virtual void attach(const QWaylandBufferRef &ref) = 0; + + friend class QtWayland::Surface; +}; + class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject { Q_OBJECT @@ -81,9 +87,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask NOTIFY orientationUpdateMaskChanged) Q_PROPERTY(QWindow::Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) -#ifdef QT_COMPOSITOR_QUICK - Q_PROPERTY(QObject * windowProperties READ windowPropertyMap CONSTANT) -#endif + Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) Q_ENUMS(WindowFlag WindowType) Q_FLAGS(WindowFlag WindowFlags) @@ -109,7 +113,8 @@ public: Texture }; - QWaylandSurface(QtWayland::Surface *surface = 0); + QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor); + virtual ~QWaylandSurface(); WaylandClient *client() const; @@ -134,27 +139,13 @@ public: WindowType windowType() const; - QImage image() const; -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint texture() const; -#else - uint texture() const; -#endif - QWindow::Visibility visibility() const; void setVisibility(QWindow::Visibility visibility); Q_INVOKABLE void sendOnScreenVisibilityChange(bool visible); // Compat QWaylandSurface *transientParent() const; - QtWayland::Surface *handle() const; - -#ifdef QT_COMPOSITOR_QUICK - QWaylandSurfaceItem *surfaceItem() const; - void setSurfaceItem(QWaylandSurfaceItem *surfaceItem); - - QObject *windowPropertyMap() const; -#endif + QtWayland::Surface *handle(); qint64 processId() const; QByteArray authenticationToken() const; @@ -175,20 +166,26 @@ public: bool transientInactive() const; + Q_INVOKABLE void destroy(); Q_INVOKABLE void destroySurface(); Q_INVOKABLE void destroySurfaceByForce(); Q_INVOKABLE void ping(); - void swapBuffers(); + void ref(); + + void setBufferAttacher(QWaylandBufferAttacher *attacher); + QWaylandBufferAttacher *bufferAttacher() const; public slots: void updateSelection(); +protected: + QWaylandSurface(QWaylandSurfacePrivate *dptr); + signals: void mapped(); void unmapped(); void damaged(const QRegion &rect); - void committed(); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void sizeChanged(); void posChanged(); @@ -204,6 +201,10 @@ signals: void lowerRequested(); void visibilityChanged(); void pong(); + void surfaceDestroyed(); + + void configure(); + void redraw(); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h new file mode 100644 index 000000000..aff0a8758 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandsurface_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSURFACE_P_H +#define QWAYLANDSURFACE_P_H + +#include <QtCompositor/qwaylandexport.h> +#include <private/qobject_p.h> + +#include <QtCompositor/private/qwlsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QWaylandCompositor; +class QWaylandSurface; + +class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public QtWayland::Surface +{ +public: + QWaylandSurfacePrivate(wl_client *client, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface); + + bool closing; + int refCount; + + friend class QWaylandSurface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index 57e5c2906..1a1dc7cdb 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -39,12 +39,9 @@ ****************************************************************************/ #include "qwaylandsurfaceitem.h" -#include "qwaylandsurface.h" -#include "qwaylandcompositor.h" -#include "qwaylandinput.h" - -#include "qwlsurface_p.h" -#include "qwlextendedsurface_p.h" +#include "qwaylandquicksurface.h" +#include <QtCompositor/qwaylandcompositor.h> +#include <QtCompositor/qwaylandinput.h> #include <QtGui/QKeyEvent> #include <QtGui/QGuiApplication> @@ -58,15 +55,15 @@ QT_BEGIN_NAMESPACE +QMutex *QWaylandSurfaceItem::mutex = 0; + class QWaylandSurfaceTextureProvider : public QSGTextureProvider { - Q_OBJECT - public: QWaylandSurfaceTextureProvider() : t(0) { } - ~QWaylandSurfaceTextureProvider() { delete t; } - QSGTexture *texture() const { + QSGTexture *texture() const Q_DECL_OVERRIDE + { if (t) t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest); return t; @@ -74,55 +71,45 @@ public: bool smooth; QSGTexture *t; - -public slots: - void invalidate() - { - delete t; - t = 0; - } }; -QMutex *QWaylandSurfaceItem::mutex = 0; - QWaylandSurfaceItem::QWaylandSurfaceItem(QQuickItem *parent) : QQuickItem(parent) , m_surface(0) , m_provider(0) , m_paintEnabled(true) - , m_useTextureAlpha(false) - , m_clientRenderingEnabled(true) , m_touchEventsEnabled(false) , m_resizeSurfaceToItem(false) + , m_newTexture(false) { if (!mutex) mutex = new QMutex; + + setFlag(ItemHasContents); } -QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *parent) +QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent) : QQuickItem(parent) , m_surface(0) , m_provider(0) , m_paintEnabled(true) - , m_useTextureAlpha(false) - , m_clientRenderingEnabled(true) , m_touchEventsEnabled(false) , m_resizeSurfaceToItem(false) { init(surface); } -void QWaylandSurfaceItem::init(QWaylandSurface *surface) +void QWaylandSurfaceItem::init(QWaylandQuickSurface *surface) { + if (m_surface) + m_surface->destroy(); + if (!surface) return; - if (m_surface) { - m_surface->setSurfaceItem(0); - } - m_surface = surface; - m_surface->setSurfaceItem(this); + surface->ref(); + update(); if (m_resizeSurfaceToItem) { updateSurfaceSize(); @@ -134,7 +121,7 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface) updatePosition(); setSmooth(true); - setFlag(ItemHasContents); + setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton | Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 | Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 | @@ -143,29 +130,29 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface) setAcceptHoverEvents(true); connect(surface, &QWaylandSurface::mapped, this, &QWaylandSurfaceItem::surfaceMapped); connect(surface, &QWaylandSurface::unmapped, this, &QWaylandSurfaceItem::surfaceUnmapped); - connect(surface, &QWaylandSurface::destroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); - connect(surface, &QWaylandSurface::damaged, this, &QWaylandSurfaceItem::surfaceDamaged); - connect(surface, &QWaylandSurface::committed, this, &QQuickItem::update); + connect(surface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); connect(surface, &QWaylandSurface::parentChanged, this, &QWaylandSurfaceItem::parentChanged); connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandSurfaceItem::updateSize); connect(surface, &QWaylandSurface::posChanged, this, &QWaylandSurfaceItem::updatePosition); + connect(surface, &QWaylandSurface::configure, this, &QWaylandSurfaceItem::updateBuffer); + connect(surface, &QWaylandSurface::redraw, this, &QQuickItem::update); connect(this, &QWaylandSurfaceItem::widthChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); connect(this, &QWaylandSurfaceItem::heightChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); - m_damaged = false; m_yInverted = surface ? surface->isYInverted() : true; + emit yInvertedChanged(); } QWaylandSurfaceItem::~QWaylandSurfaceItem() { QMutexLocker locker(mutex); if (m_surface) - m_surface->setSurfaceItem(0); + m_surface->destroy(); if (m_provider) m_provider->deleteLater(); } -void QWaylandSurfaceItem::setSurface(QWaylandSurface *surface) +void QWaylandSurfaceItem::setSurface(QWaylandQuickSurface *surface) { if (surface == m_surface) return; @@ -181,16 +168,9 @@ bool QWaylandSurfaceItem::isYInverted() const QSGTextureProvider *QWaylandSurfaceItem::textureProvider() const { - const_cast<QWaylandSurfaceItem *>(this)->ensureProvider(); - return m_provider; -} - -void QWaylandSurfaceItem::ensureProvider() -{ - if (!m_provider) { + if (!m_provider) m_provider = new QWaylandSurfaceTextureProvider(); - connect(window(), &QQuickWindow::sceneGraphInvalidated, m_provider, &QWaylandSurfaceTextureProvider::invalidate, Qt::DirectConnection); - } + return m_provider; } void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event) @@ -281,40 +261,10 @@ void QWaylandSurfaceItem::surfaceUnmapped() update(); } -void QWaylandSurfaceItem::surfaceDestroyed(QObject *) -{ - if (m_surface) - m_surface->setSurfaceItem(0); - - m_surface = 0; -} - -void QWaylandSurfaceItem::setDamagedFlag(bool on) -{ - m_damaged = on; -} - - -void QWaylandSurfaceItem::surfaceDamaged(const QRegion &) -{ - m_damaged = true; - if (m_surface) { - bool inverted = m_surface->isYInverted(); - if (inverted != m_yInverted) { - m_yInverted = inverted; - emit yInvertedChanged(); - } - } - emit textureChanged(); -} - void QWaylandSurfaceItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent) { Q_UNUSED(oldParent); - QWaylandSurfaceItem *item = newParent? newParent->surfaceItem():0; - setParentItem(item); - if (newParent) { setPaintEnabled(true); setVisible(true); @@ -340,6 +290,14 @@ void QWaylandSurfaceItem::updatePosition() setPosition(m_surface->pos()); } +/*! + \qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled + + If this property is true, the \l item is hidden, though the texture + will still be updated. As opposed to hiding the \l item by + setting \l{Item::visible}{visible} to false, setting this property to true + will not prevent mouse or keyboard input from reaching \l item. +*/ bool QWaylandSurfaceItem::paintEnabled() const { return m_paintEnabled; @@ -351,29 +309,14 @@ void QWaylandSurfaceItem::setPaintEnabled(bool enabled) update(); } -void QWaylandSurfaceItem::updateTexture() +void QWaylandSurfaceItem::updateBuffer() { - ensureProvider(); - QSGTexture *texture = m_provider->t; - if (m_damaged) { - m_damaged = false; - QSGTexture *oldTexture = texture; - if (m_surface->type() == QWaylandSurface::Texture) { - QQuickWindow::CreateTextureOptions opt = 0; - if (useTextureAlpha()) { - opt |= QQuickWindow::TextureHasAlphaChannel; - } - texture = window()->createTextureFromId(m_surface->texture(), m_surface->size(), opt); - } else { - texture = window()->createTextureFromImage(m_surface->image()); - } - texture->bind(); - delete oldTexture; - } + bool inv = m_yInverted; + m_yInverted = surface()->isYInverted(); + if (inv != m_yInverted) + emit yInvertedChanged(); - m_provider->t = texture; - emit m_provider->textureChanged(); - m_provider->smooth = smooth(); + m_newTexture = true; } QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) @@ -383,14 +326,20 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD return 0; } + if (!m_provider) + m_provider = new QWaylandSurfaceTextureProvider(); + // Order here is important, as the state of visible is that of the pending // buffer but will be replaced after we advance the buffer queue. bool mapped = m_surface->isMapped(); - surface()->swapBuffers(); if (mapped) - updateTexture(); + m_provider->t = surface()->texture(); + m_provider->smooth = smooth(); + if (m_newTexture) + emit m_provider->textureChanged(); + m_newTexture = false; - if (!mapped|| !m_provider || !m_provider->t || !m_paintEnabled) { + if (!mapped || !m_provider->t || !m_paintEnabled) { delete oldNode; return 0; } @@ -409,28 +358,6 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD return node; } -void QWaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha) -{ - m_useTextureAlpha = useTextureAlpha; - - if ((flags() & ItemHasContents) != 0) { - update(); - } -} - -void QWaylandSurfaceItem::setClientRenderingEnabled(bool enabled) -{ - if (m_clientRenderingEnabled != enabled) { - m_clientRenderingEnabled = enabled; - - if (m_surface) { - m_surface->sendOnScreenVisibilityChange(enabled); - } - - emit clientRenderingEnabledChanged(); - } -} - void QWaylandSurfaceItem::setTouchEventsEnabled(bool enabled) { if (m_touchEventsEnabled != enabled) { @@ -448,5 +375,3 @@ void QWaylandSurfaceItem::setResizeSurfaceToItem(bool enabled) } QT_END_NAMESPACE - -#include "qwaylandsurfaceitem.moc" diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h index 8abd4bf2d..f1da27995 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h @@ -42,38 +42,37 @@ #define QWAYLANDSURFACEITEM_H #include <QtCompositor/qwaylandexport.h> -#include <QtCompositor/qwaylandsurface.h> #include <QtQuick/QQuickItem> #include <QtQuick/qsgtexture.h> #include <QtQuick/qsgtextureprovider.h> +#include "qwaylandquicksurface.h" + QT_BEGIN_NAMESPACE class QWaylandSurfaceTextureProvider; class QMutex; -Q_DECLARE_METATYPE(QWaylandSurface*) +Q_DECLARE_METATYPE(QWaylandQuickSurface*) -class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem +class QWaylandSurfaceItem : public QQuickItem { Q_OBJECT - Q_PROPERTY(QWaylandSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged) + Q_PROPERTY(QWaylandQuickSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged) Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) - Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged) - Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged) Q_PROPERTY(bool isYInverted READ isYInverted NOTIFY yInvertedChanged) Q_PROPERTY(bool resizeSurfaceToItem READ resizeSurfaceToItem WRITE setResizeSurfaceToItem NOTIFY resizeSurfaceToItemChanged) public: QWaylandSurfaceItem(QQuickItem *parent = 0); - QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *parent = 0); + QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent = 0); ~QWaylandSurfaceItem(); - void setSurface(QWaylandSurface *surface); - QWaylandSurface *surface() const {return m_surface; } + void setSurface(QWaylandQuickSurface *surface); + QWaylandQuickSurface *surface() const {return m_surface; } Q_INVOKABLE bool isYInverted() const; @@ -81,18 +80,12 @@ public: QSGTextureProvider *textureProvider() const; bool paintEnabled() const; - bool useTextureAlpha() const { return m_useTextureAlpha; } - bool clientRenderingEnabled() const { return m_clientRenderingEnabled; } bool touchEventsEnabled() const { return m_touchEventsEnabled; } bool resizeSurfaceToItem() const { return m_resizeSurfaceToItem; } - void setUseTextureAlpha(bool useTextureAlpha); - void setClientRenderingEnabled(bool enabled); void setTouchEventsEnabled(bool enabled); void setResizeSurfaceToItem(bool enabled); - void setDamagedFlag(bool on); - protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); @@ -111,21 +104,18 @@ public slots: private slots: void surfaceMapped(); void surfaceUnmapped(); - void surfaceDestroyed(QObject *object); - void surfaceDamaged(const QRegion &); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void updateSize(); void updateSurfaceSize(); void updatePosition(); + void updateBuffer(); signals: - void textureChanged(); - void useTextureAlphaChanged(); - void clientRenderingEnabledChanged(); void touchEventsEnabledChanged(); void yInvertedChanged(); void surfaceChanged(); void resizeSurfaceToItemChanged(); + void surfaceDestroyed(); protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); @@ -133,20 +123,17 @@ protected: private: friend class QWaylandSurfaceNode; void updateTexture(); - void init(QWaylandSurface *); - void ensureProvider(); + void init(QWaylandQuickSurface *); static QMutex *mutex; - QWaylandSurface *m_surface; - QWaylandSurfaceTextureProvider *m_provider; + QWaylandQuickSurface *m_surface; + mutable QWaylandSurfaceTextureProvider *m_provider; bool m_paintEnabled; - bool m_useTextureAlpha; - bool m_clientRenderingEnabled; bool m_touchEventsEnabled; - bool m_damaged; bool m_yInverted; bool m_resizeSurfaceToItem; + bool m_newTexture; }; QT_END_NAMESPACE |