diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2017-05-22 16:44:56 +0200 |
---|---|---|
committer | Johan Helsing <johan.helsing@qt.io> | 2018-02-09 10:29:16 +0000 |
commit | 062e7bffc7a60ebe3bb95fc736aabbafbb01cf6b (patch) | |
tree | ab678cbd5c33b360b1ca36780d6f461af62bf789 | |
parent | 8b204b2c56be5e7c1fd21144ae140c9b865dd86b (diff) | |
download | qtwayland-062e7bffc7a60ebe3bb95fc736aabbafbb01cf6b.tar.gz |
Compositor API: Add support for hardware compositing
[ChangeLog][Compositor] Add a tech preview for a plugin-based hardware layer
API and a VSP2 implementation (for Renesas R-Car M3 and H3).
Task-number: QTBUG-64600
Task-number: QTBUG-64604
Change-Id: Ia4abfb6343cf4f006ba408d293ec9464cd6f31b7
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
32 files changed, 1489 insertions, 9 deletions
diff --git a/examples/wayland/hwlayer-compositor/.gitignore b/examples/wayland/hwlayer-compositor/.gitignore new file mode 100644 index 00000000..83a421ca --- /dev/null +++ b/examples/wayland/hwlayer-compositor/.gitignore @@ -0,0 +1 @@ +hwlayer-compositor diff --git a/examples/wayland/hwlayer-compositor/hwlayer-compositor.pro b/examples/wayland/hwlayer-compositor/hwlayer-compositor.pro new file mode 100644 index 00000000..a6eed907 --- /dev/null +++ b/examples/wayland/hwlayer-compositor/hwlayer-compositor.pro @@ -0,0 +1,14 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + main.qml + +RESOURCES += hwlayer-compositor.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/hwlayer-compositor +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS hwlayer-compositor.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/hwlayer-compositor +INSTALLS += target sources diff --git a/examples/wayland/hwlayer-compositor/hwlayer-compositor.qrc b/examples/wayland/hwlayer-compositor/hwlayer-compositor.qrc new file mode 100644 index 00000000..5f6483ac --- /dev/null +++ b/examples/wayland/hwlayer-compositor/hwlayer-compositor.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/hwlayer-compositor/main.cpp b/examples/wayland/hwlayer-compositor/main.cpp new file mode 100644 index 00000000..d2646638 --- /dev/null +++ b/examples/wayland/hwlayer-compositor/main.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QUrl> +#include <QtCore/QDebug> + +#include <QtGui/QGuiApplication> +#include <QQmlContext> + +#include <QtQml/QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + QQmlApplicationEngine appEngine(QUrl("qrc:///main.qml")); + return app.exec(); +} diff --git a/examples/wayland/hwlayer-compositor/main.qml b/examples/wayland/hwlayer-compositor/main.qml new file mode 100644 index 00000000..de4fe6d4 --- /dev/null +++ b/examples/wayland/hwlayer-compositor/main.qml @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.2 +import QtWayland.Compositor 1.2 + +WaylandCompositor { + WaylandOutput { + sizeFollowsWindow: true + window: Window { + color: "tomato" + id: win + width: 1024 + height: 768 + visible: true + Rectangle { + color: "lightgreen" + anchors.centerIn: parent + width: parent.width / 3 + height: parent.width / 3 + NumberAnimation on rotation { + id: rotationAnimation + running: false + from: 0 + to: 90 + loops: Animation.Infinite + duration: 1000 + } + } + Repeater { + model: shellSurfaces + ShellSurfaceItem { + id: waylandItem + onSurfaceDestroyed: shellSurfaces.remove(index) + shellSurface: shSurface + WaylandHardwareLayer { + stackingLevel: level + Component.onCompleted: console.log("Added hardware layer with stacking level", stackingLevel); + } + Component.onCompleted: console.log("Added wayland quick item"); + Behavior on x { + PropertyAnimation { + easing.type: Easing.OutBounce + duration: 1000 + } + } + Timer { + interval: 2000; running: animatePosition; repeat: true + onTriggered: waylandItem.x = waylandItem.x === 0 ? win.width - waylandItem.width : 0 + } + Behavior on opacity { + PropertyAnimation { + duration: 1000 + } + } + Timer { + interval: 2000; running: animateOpacity; repeat: true + onTriggered: waylandItem.opacity = waylandItem.opacity === 1 ? 0 : 1 + } + } + } + Column { + anchors.bottom: parent.bottom + Repeater { + model: shellSurfaces + Row { + Label { + anchors.verticalCenter: parent.verticalCenter + leftPadding: 15 + rightPadding: 15 + text: "Surface " + index + } + CheckBox { + text: "Animate position" + checked: animatePosition + onClicked: animatePosition = !animatePosition + } + CheckBox { + text: "Animate Opacity" + checked: animateOpacity + onClicked: animateOpacity = !animateOpacity + } + Label { + text: "Stacking level" + } + SpinBox { + value: level + onValueModified: level = value; + } + Button { + text: "Kill" + onClicked: shSurface.surface.client.close() + } + } + } + CheckBox { + text: "Rotation" + checked: rotationAnimation.running + onClicked: rotationAnimation.running = !rotationAnimation.running + padding: 30 + } + } + } + } + ListModel { id: shellSurfaces } + function addShellSurface(shellSurface) { + shellSurfaces.append({shSurface: shellSurface, animatePosition: false, animateOpacity: false, level: 0}); + } + WlShell { onWlShellSurfaceCreated: addShellSurface(shellSurface) } + XdgShellV5 { onXdgSurfaceCreated: addShellSurface(xdgSurface) } + XdgShellV6 { onToplevelCreated: addShellSurface(xdgSurface) } +} diff --git a/examples/wayland/wayland.pro b/examples/wayland/wayland.pro index 9da43fbd..a8eef826 100644 --- a/examples/wayland/wayland.pro +++ b/examples/wayland/wayland.pro @@ -18,4 +18,5 @@ qtHaveModule(quick) { custom-extension \ server-buffer } + SUBDIRS += hwlayer-compositor } diff --git a/src/compositor/compositor.pro b/src/compositor/compositor.pro index dc9000d9..47be591d 100644 --- a/src/compositor/compositor.pro +++ b/src/compositor/compositor.pro @@ -30,5 +30,7 @@ include ($$PWD/compositor_api/compositor_api.pri) include ($$PWD/extensions/extensions.pri) MODULE_PLUGIN_TYPES = \ - wayland-graphics-integration-server + wayland-graphics-integration-server \ + wayland-hardware-layer-integration \ + load(qt_module) diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index 35f57f80..e5df0f1f 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -26,7 +26,8 @@ HEADERS += \ compositor_api/qwaylandview_p.h \ compositor_api/qwaylandresource.h \ compositor_api/qwaylandsurfacegrabber.h \ - compositor_api/qwaylandoutputmode_p.h + compositor_api/qwaylandoutputmode_p.h \ + compositor_api/qwaylandquickhardwarelayer_p.h \ SOURCES += \ compositor_api/qwaylandcompositor.cpp \ @@ -43,7 +44,8 @@ SOURCES += \ compositor_api/qwaylanddestroylistener.cpp \ compositor_api/qwaylandview.cpp \ compositor_api/qwaylandresource.cpp \ - compositor_api/qwaylandsurfacegrabber.cpp + compositor_api/qwaylandsurfacegrabber.cpp \ + compositor_api/qwaylandquickhardwarelayer.cpp qtConfig(im) { HEADERS += \ diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp index 9cbf80fd..7627195d 100644 --- a/src/compositor/compositor_api/qwaylandoutput.cpp +++ b/src/compositor/compositor_api/qwaylandoutput.cpp @@ -46,6 +46,7 @@ #include <QtWaylandCompositor/private/qwaylandsurface_p.h> #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwaylandview_p.h> #include <QtCore/QCoreApplication> #include <QtCore/QtMath> @@ -895,8 +896,10 @@ void QWaylandOutput::sendFrameCallbacks() surfaceEnter(surfacemapper.surface); d->surfaceViews[i].has_entered = true; } - if (surfacemapper.maybePrimaryView()) - surfacemapper.surface->sendFrameCallbacks(); + if (auto primaryView = surfacemapper.maybePrimaryView()) { + if (!QWaylandViewPrivate::get(primaryView)->independentFrameCallback) + surfacemapper.surface->sendFrameCallbacks(); + } } } wl_display_flush_clients(d->compositor->display()); diff --git a/src/compositor/compositor_api/qwaylandquickhardwarelayer.cpp b/src/compositor/compositor_api/qwaylandquickhardwarelayer.cpp new file mode 100644 index 00000000..f82de001 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickhardwarelayer.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandquickhardwarelayer_p.h" + +#include <QtWaylandCompositor/private/qwlhardwarelayerintegration_p.h> +#include <QtWaylandCompositor/private/qwlhardwarelayerintegrationfactory_p.h> + +#include <QtCore/private/qobject_p.h> +#include <QMatrix4x4> + +QT_BEGIN_NAMESPACE + +class QWaylandQuickHardwareLayerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandQuickHardwareLayer) +public: + QtWayland::HardwareLayerIntegration *layerIntegration(); + QWaylandQuickItem *m_waylandItem = nullptr; + int m_stackingLevel = 0; + QMatrix4x4 m_matrixFromRenderThread; + static QtWayland::HardwareLayerIntegration *s_hardwareLayerIntegration; +}; + +QtWayland::HardwareLayerIntegration *QWaylandQuickHardwareLayerPrivate::s_hardwareLayerIntegration = nullptr; + +QtWayland::HardwareLayerIntegration *QWaylandQuickHardwareLayerPrivate::layerIntegration() +{ + if (!s_hardwareLayerIntegration) { + QStringList keys = QtWayland::HardwareLayerIntegrationFactory::keys(); + + QString environmentKey = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_HARDWARE_LAYER_INTEGRATION").constData()); + if (!environmentKey.isEmpty()) { + if (keys.contains(environmentKey)) { + s_hardwareLayerIntegration = QtWayland::HardwareLayerIntegrationFactory::create(environmentKey, QStringList()); + } else { + qWarning() << "Unknown hardware layer integration:" << environmentKey + << "Valid layer integrations are" << keys; + } + } else if (!keys.isEmpty()) { + s_hardwareLayerIntegration = QtWayland::HardwareLayerIntegrationFactory::create(keys.first(), QStringList()); + } else { + qWarning() << "No wayland hardware layer integrations found"; + } + } + + return s_hardwareLayerIntegration; +} + +/*! + * \qmltype WaylandHardwareLayer + * \inqmlmodule QtWayland.Compositor + * \preliminary + * \brief Makes a parent WaylandQuickItem use hardware layers for rendering + * + * This item needs to be a descendant of a WaylandQuickItem or a derivative, + * (i.e. ShellSurfaceItem or similar) + * + * The Surface of the parent WaylandQuickItem will be drawn in a hardware specific way instead + * of the regular way using the QtQuick scene graph. On some platforms, the WaylandQuickItem's + * current buffer and the scene graph can be blended in a separate step. This makes it possible for + * clients to update continuously without triggering a full redraw of the compositor scene graph for + * each frame. + * + * The preferred hardware layer integration may be overridden by setting the + * QT_WAYLAND_HARDWARE_LAYER_INTEGRATION environment variable. + */ + +QWaylandQuickHardwareLayer::QWaylandQuickHardwareLayer(QObject *parent) + : QObject(*new QWaylandQuickHardwareLayerPrivate(), parent) +{ +} + +QWaylandQuickHardwareLayer::~QWaylandQuickHardwareLayer() +{ + Q_D(QWaylandQuickHardwareLayer); + if (d->layerIntegration()) + d->layerIntegration()->remove(this); +} + +/*! + * \qmlproperty int QtWaylandCompositor::WaylandHardwareLayer::stackingLevel + * + * This property holds the stacking level of this hardware layer relative to other hardware layers, + * and can be used to sort hardware layers. I.e. a layer with a higher level is rendered on top of + * one with a lower level. + * + * Layers with level 0 will be drawn in an implementation defined order on top of the compositor + * scene graph. + * + * Layers with a level below 0 are drawn beneath the compositor scene graph, if supported by the + * hardware layer integration. + */ +int QWaylandQuickHardwareLayer::stackingLevel() const +{ + Q_D(const QWaylandQuickHardwareLayer); + return d->m_stackingLevel; +} + +void QWaylandQuickHardwareLayer::setStackingLevel(int level) +{ + Q_D(QWaylandQuickHardwareLayer); + if (level == d->m_stackingLevel) + return; + + d->m_stackingLevel = level; + emit stackingLevelChanged(); +} + +QWaylandQuickItem *QWaylandQuickHardwareLayer::waylandItem() const +{ + Q_D(const QWaylandQuickHardwareLayer); + return d->m_waylandItem; +} + +void QWaylandQuickHardwareLayer::classBegin() +{ + Q_D(QWaylandQuickHardwareLayer); + for (QObject *p = parent(); p != nullptr; p = p->parent()) { + if (auto *waylandItem = qobject_cast<QWaylandQuickItem *>(p)) { + d->m_waylandItem = waylandItem; + break; + } + } +} + +void QWaylandQuickHardwareLayer::componentComplete() +{ + Q_D(QWaylandQuickHardwareLayer); + Q_ASSERT(d->m_waylandItem); + if (auto integration = d->layerIntegration()) + integration->add(this); + else + qWarning() << "No hardware layer integration. WaylandHarwareLayer has no effect."; +} + +void QWaylandQuickHardwareLayer::disableSceneGraphPainting() +{ + waylandItem()->setPaintEnabled(false); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickhardwarelayer_p.h b/src/compositor/compositor_api/qwaylandquickhardwarelayer_p.h new file mode 100644 index 00000000..24cb709f --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickhardwarelayer_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDQUICKHARDWARELAYER_P_H +#define QWAYLANDQUICKHARDWARELAYER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandCompositor/QWaylandQuickItem> + +QT_BEGIN_NAMESPACE + +class QWaylandQuickHardwareLayerPrivate; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickHardwareLayer : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_DECLARE_PRIVATE(QWaylandQuickHardwareLayer) + Q_PROPERTY(int stackingLevel READ stackingLevel WRITE setStackingLevel NOTIFY stackingLevelChanged) +public: + explicit QWaylandQuickHardwareLayer(QObject *parent = nullptr); + ~QWaylandQuickHardwareLayer() override; + + int stackingLevel() const; + void setStackingLevel(int level); + + QWaylandQuickItem *waylandItem() const; + + void classBegin() override; + void componentComplete() override; + + void disableSceneGraphPainting(); + +Q_SIGNALS: + void stackingLevelChanged(); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDQUICKHARDWARELAYER_P_H diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index de5a36cd..ff904331 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -1190,9 +1190,10 @@ void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries) * \sa QWaylandQuickkItem::bufferLocked */ -QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) { Q_D(QWaylandQuickItem); + d->lastMatrix = data->transformNode->combinedMatrix(); const bool bufferHasContent = d->view->currentBuffer().hasContent(); if (d->view->isBufferLocked() && !bufferHasContent && d->paintEnabled) @@ -1200,7 +1201,7 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat if (!bufferHasContent || !d->paintEnabled) { delete oldNode; - return 0; + return nullptr; } QWaylandBufferRef ref = d->view->currentBuffer(); diff --git a/src/compositor/compositor_api/qwaylandquickitem.h b/src/compositor/compositor_api/qwaylandquickitem.h index cd44a4fb..11457fa6 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.h +++ b/src/compositor/compositor_api/qwaylandquickitem.h @@ -184,7 +184,7 @@ Q_SIGNALS: void bufferLockedChanged(); void allowDiscardFrontBufferChanged(); protected: - QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override; + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) override; QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *parent = nullptr); }; diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h index 98af6ba7..400cda74 100644 --- a/src/compositor/compositor_api/qwaylandquickitem_p.h +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -149,6 +149,8 @@ public: q->updateWindow(); } + static const QWaylandQuickItemPrivate* get(const QWaylandQuickItem *item) { return item->d_func(); } + void setInputEventsEnabled(bool enable) { Q_Q(QWaylandQuickItem); @@ -177,6 +179,7 @@ public: bool focusOnClick; bool sizeFollowsSurface; QPoint hoverPos; + QMatrix4x4 lastMatrix; QQuickWindow *connectedWindow; QWaylandSurface::Origin origin; diff --git a/src/compositor/compositor_api/qwaylandview_p.h b/src/compositor/compositor_api/qwaylandview_p.h index a2bf219d..1cc55954 100644 --- a/src/compositor/compositor_api/qwaylandview_p.h +++ b/src/compositor/compositor_api/qwaylandview_p.h @@ -40,6 +40,8 @@ #ifndef QWAYLANDSURFACEVIEW_P_H #define QWAYLANDSURFACEVIEW_P_H +#include "qwaylandview.h" + #include <QtCore/QPoint> #include <QtCore/QMutex> #include <QtCore/private/qobject_p.h> @@ -95,6 +97,7 @@ public: bool broadcastRequestedPositionChanged; bool forceAdvanceSucceed; bool allowDiscardFrontBuffer; + bool independentFrameCallback = false; //If frame callbacks are independent of the main quick scene graph }; QT_END_NAMESPACE diff --git a/src/compositor/configure.json b/src/compositor/configure.json index a95c4eb0..21f486d7 100644 --- a/src/compositor/configure.json +++ b/src/compositor/configure.json @@ -22,6 +22,26 @@ "-lEGL" ] }, + "wayland-kms": { + "label": "wayland-kms", + "test": { + "tail": [ + "extern \"C\" {", + "#define private priv", + "#include <wayland-kms.h>", + "#undef private", + "}" + ], + "main": [ + "struct wl_resource *buffer = nullptr;", + "struct wl_kms_buffer *kmsBuffer = wayland_kms_buffer_get(buffer);" + ] + }, + "sources": [ + { "type": "pkgConfig", "args": "wayland-kms" }, + "-lwayland-kms" + ] + }, "xcomposite": { "test": "xcomposite", "sources": [ @@ -95,10 +115,22 @@ "label": "libhybris EGL", "condition": "features.wayland-server && features.opengl && features.egl && tests.libhybris-egl-server", "output": [ "privateFeature" ] + }, + "wayland-layer-integration-vsp2": { + "label": "VSP2 hardware layer integration", + "condition": "features.wayland-server && features.eglfs_vsp2 && libs.wayland-kms", + "output": [ "privateFeature" ] } }, "summary": [ - "wayland-server" + "wayland-server", + { + "section": "Qt Wayland Compositor Layer Plugins", + "condition": "features.wayland-server", + "entries": [ + "wayland-layer-integration-vsp2" + ] + } ] } diff --git a/src/compositor/hardware_integration/hardware_integration.pri b/src/compositor/hardware_integration/hardware_integration.pri index dd892e07..6bf7a75b 100644 --- a/src/compositor/hardware_integration/hardware_integration.pri +++ b/src/compositor/hardware_integration/hardware_integration.pri @@ -12,6 +12,9 @@ qtConfig(opengl) { hardware_integration/qwlserverbufferintegrationfactory_p.h \ hardware_integration/qwlserverbufferintegrationplugin_p.h \ hardware_integration/qwlhwintegration_p.h \ + hardware_integration/qwlhardwarelayerintegration_p.h \ + hardware_integration/qwlhardwarelayerintegrationfactory_p.h \ + hardware_integration/qwlhardwarelayerintegrationplugin_p.h \ SOURCES += \ hardware_integration/qwlclientbufferintegration.cpp \ @@ -21,6 +24,9 @@ qtConfig(opengl) { hardware_integration/qwlserverbufferintegrationfactory.cpp \ hardware_integration/qwlserverbufferintegrationplugin.cpp \ hardware_integration/qwlhwintegration.cpp \ + hardware_integration/qwlhardwarelayerintegration.cpp \ + hardware_integration/qwlhardwarelayerintegrationfactory.cpp \ + hardware_integration/qwlhardwarelayerintegrationplugin.cpp \ } else { system(echo "Qt-Compositor configured as raster only compositor") } diff --git a/src/compositor/hardware_integration/qwlhardwarelayerintegration.cpp b/src/compositor/hardware_integration/qwlhardwarelayerintegration.cpp new file mode 100644 index 00000000..76cf0990 --- /dev/null +++ b/src/compositor/hardware_integration/qwlhardwarelayerintegration.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwlhardwarelayerintegration_p.h" + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +} + +QT_END_NAMESPACE diff --git a/src/compositor/hardware_integration/qwlhardwarelayerintegration_p.h b/src/compositor/hardware_integration/qwlhardwarelayerintegration_p.h new file mode 100644 index 00000000..02de8e8b --- /dev/null +++ b/src/compositor/hardware_integration/qwlhardwarelayerintegration_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDHARDWARELAYERINTEGRATION_H +#define QWAYLANDHARDWARELAYERINTEGRATION_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandCompositor/qtwaylandcompositorglobal.h> + +#include <QObject> +#include <QQmlParserStatus> + +QT_BEGIN_NAMESPACE + +class QPoint; + +class QWaylandQuickHardwareLayer; + +namespace QtWayland { + +class Q_WAYLAND_COMPOSITOR_EXPORT HardwareLayerIntegration : public QObject +{ + Q_OBJECT +public: + HardwareLayerIntegration(QObject *parent = nullptr) + : QObject(parent) + {} + ~HardwareLayerIntegration() override {} + virtual void add(QWaylandQuickHardwareLayer *) {} + virtual void remove(QWaylandQuickHardwareLayer *) {} +}; + +} // namespace QtWayland + +QT_END_NAMESPACE + +#endif // QWAYLANDHARDWARELAYERINTEGRATION_H diff --git a/src/compositor/hardware_integration/qwlhardwarelayerintegrationfactory.cpp b/src/compositor/hardware_integration/qwlhardwarelayerintegrationfactory.cpp new file mode 100644 index 00000000..4b85be82 --- /dev/null +++ b/src/compositor/hardware_integration/qwlhardwarelayerintegrationfactory.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwlhardwarelayerintegrationfactory_p.h" +#include "qwlhardwarelayerintegrationplugin_p.h" +#include "qwlhardwarelayerintegration_p.h" + +#include <QtCore/private/qfactoryloader_p.h> +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +#if QT_CONFIG(library) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QtWaylandHardwareLayerIntegrationFactoryInterface_iid, QLatin1String("/wayland-hardware-layer-integration"), Qt::CaseInsensitive)) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, + (QtWaylandHardwareLayerIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) +#endif + +QStringList HardwareLayerIntegrationFactory::keys(const QString &pluginPath) +{ +#if QT_CONFIG(library) + QStringList list; + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + list = directLoader()->keyMap().values(); + if (!list.isEmpty()) { + const QString postFix = QStringLiteral(" (from ") + + QDir::toNativeSeparators(pluginPath) + + QLatin1Char(')'); + const QStringList::iterator end = list.end(); + for (QStringList::iterator it = list.begin(); it != end; ++it) + (*it).append(postFix); + } + } + list.append(loader()->keyMap().values()); + return list; +#else + return QStringList(); +#endif +} + +HardwareLayerIntegration *HardwareLayerIntegrationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath) +{ +#if QT_CONFIG(library) + // Try loading the plugin from platformPluginPath first: + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + if (HardwareLayerIntegration *ret = qLoadPlugin<HardwareLayerIntegration, HardwareLayerIntegrationPlugin>(directLoader(), name, args)) + return ret; + } + if (HardwareLayerIntegration *ret = qLoadPlugin<HardwareLayerIntegration, HardwareLayerIntegrationPlugin>(loader(), name, args)) + return ret; +#endif + return nullptr; +} + +} + +QT_END_NAMESPACE diff --git a/src/compositor/hardware_integration/qwlhardwarelayerintegrationfactory_p.h b/src/compositor/hardware_integration/qwlhardwarelayerintegrationfactory_p.h new file mode 100644 index 00000000..83c9c523 --- /dev/null +++ b/src/compositor/hardware_integration/qwlhardwarelayerintegrationfactory_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDHARDWARELAYERINTEGRATIONFACTORY_H +#define QWAYLANDHARDWARELAYERINTEGRATIONFACTORY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandCompositor/qtwaylandcompositorglobal.h> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +class HardwareLayerIntegration; + +class Q_WAYLAND_COMPOSITOR_EXPORT HardwareLayerIntegrationFactory +{ +public: + static QStringList keys(const QString &pluginPath = QString()); + static HardwareLayerIntegration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString()); +}; + +} + +QT_END_NAMESPACE + +#endif // QWAYLANDHARDWARELAYERINTEGRATIONFACTORY_H diff --git a/src/compositor/hardware_integration/qwlhardwarelayerintegrationplugin.cpp b/src/compositor/hardware_integration/qwlhardwarelayerintegrationplugin.cpp new file mode 100644 index 00000000..0ae3a0b6 --- /dev/null +++ b/src/compositor/hardware_integration/qwlhardwarelayerintegrationplugin.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwlhardwarelayerintegrationplugin_p.h" + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +HardwareLayerIntegrationPlugin::HardwareLayerIntegrationPlugin(QObject *parent) : + QObject(parent) +{ +} + +HardwareLayerIntegrationPlugin::~HardwareLayerIntegrationPlugin() +{ +} + +} + +QT_END_NAMESPACE diff --git a/src/compositor/hardware_integration/qwlhardwarelayerintegrationplugin_p.h b/src/compositor/hardware_integration/qwlhardwarelayerintegrationplugin_p.h new file mode 100644 index 00000000..acf80fe3 --- /dev/null +++ b/src/compositor/hardware_integration/qwlhardwarelayerintegrationplugin_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDHARDWARELAYERINTEGRATIONPLUGIN_H +#define QWAYLANDHARDWARELAYERINTEGRATIONPLUGIN_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandCompositor/qtwaylandcompositorglobal.h> + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +class HardwareLayerIntegration; + +#define QtWaylandHardwareLayerIntegrationFactoryInterface_iid "org.qt-project.Qt.Compositor.QtWaylandHardwareLayerIntegrationFactoryInterface.5.11" + +class Q_WAYLAND_COMPOSITOR_EXPORT HardwareLayerIntegrationPlugin : public QObject +{ + Q_OBJECT +public: + explicit HardwareLayerIntegrationPlugin(QObject *parent = nullptr); + ~HardwareLayerIntegrationPlugin() override; + + virtual HardwareLayerIntegration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +} + +QT_END_NAMESPACE + +#endif // QWAYLANDHARDWARELAYERINTEGRATIONPLUGIN_H diff --git a/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pri b/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pri new file mode 100644 index 00000000..9d68775b --- /dev/null +++ b/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pri @@ -0,0 +1,9 @@ +INCLUDEPATH += $$PWD + +QMAKE_USE_PRIVATE += wayland-server + +SOURCES += \ + $$PWD/vsp2hardwarelayerintegration.cpp + +HEADERS += \ + $$PWD/vsp2hardwarelayerintegration.h diff --git a/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2hardwarelayerintegration.cpp b/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2hardwarelayerintegration.cpp new file mode 100644 index 00000000..a02226a5 --- /dev/null +++ b/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2hardwarelayerintegration.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "vsp2hardwarelayerintegration.h" + +extern "C" { +#define private priv +#include <wayland-kms.h> +#undef private +} + +#include <private/qwaylandquickhardwarelayer_p.h> +#include <private/qwaylandquickitem_p.h> +#include <private/qwaylandview_p.h> +#include <QWaylandQuickOutput> +#include <QQuickWindow> + +#include <QtPlatformHeaders/qeglfsfunctions.h> + +QT_BEGIN_NAMESPACE + +Vsp2Buffer::Vsp2Buffer(wl_kms_buffer *kmsBuffer) + : dmabufFd(kmsBuffer->fd) + , bytesPerLine(kmsBuffer->stride) + , drmPixelFormat(kmsBuffer->format) + , size(kmsBuffer->width, kmsBuffer->height) +{ +} + +Vsp2Layer::Vsp2Layer(QWaylandQuickHardwareLayer *hwLayer, Vsp2HardwareLayerIntegration *integration) + : m_hwLayer(hwLayer) +{ + connect(hwLayer, &QWaylandQuickHardwareLayer::stackingLevelChanged, this, [integration](){ + integration->recreateVspLayers(); + }); + connect(hwLayer->waylandItem(), &QWaylandQuickItem::surfaceChanged, this, &Vsp2Layer::handleSurfaceChanged); + connect(hwLayer->waylandItem(), &QQuickItem::opacityChanged, this, &Vsp2Layer::updateOpacity); + connect(hwLayer->waylandItem()->window(), &QQuickWindow::afterSynchronizing, this, &Vsp2Layer::updatePosition); + hwLayer->disableSceneGraphPainting(); + QWaylandViewPrivate::get(hwLayer->waylandItem()->view())->independentFrameCallback = true; + handleSurfaceChanged(); +} + +void Vsp2Layer::enableVspLayer() +{ + auto *kmsBuffer = nextKmsBuffer(); + + if (!kmsBuffer) + return; + + m_buffer = Vsp2Buffer(kmsBuffer); + updatePosition(); + auto *wlItem = m_hwLayer->waylandItem(); + m_screen = wlItem->window()->screen(); + m_layerIndex = QEglFSFunctions::vsp2AddLayer(m_screen, m_buffer.dmabufFd, m_buffer.size, m_position, m_buffer.drmPixelFormat, m_buffer.bytesPerLine); + wlItem->surface()->frameStarted(); + updateOpacity(); +} + +void Vsp2Layer::disableVspLayer() +{ + QEglFSFunctions::vsp2RemoveLayer(m_screen, m_layerIndex); + m_layerIndex = -1; + m_screen = nullptr; +} + +void Vsp2Layer::handleBufferCommitted() +{ + if (!isEnabled()) { + enableVspLayer(); + return; + } + + auto *kmsBuffer = nextKmsBuffer(); + + Vsp2Buffer newBuffer(kmsBuffer); + if (m_buffer.dmabufFd != -1) { + bool formatChanged = false; + formatChanged |= newBuffer.bytesPerLine != m_buffer.bytesPerLine; + formatChanged |= newBuffer.size != m_buffer.size; + formatChanged |= newBuffer.drmPixelFormat != m_buffer.drmPixelFormat; + if (formatChanged) { + qWarning() << "The VSP2 Wayland hardware layer integration doesn't support changing" + << "surface formats, this will most likely fail"; + } + } + + m_buffer = newBuffer; + auto *wlItem = m_hwLayer->waylandItem(); + m_screen = wlItem->window()->screen(); + QEglFSFunctions::vsp2SetLayerBuffer(m_screen, m_layerIndex, m_buffer.dmabufFd); + wlItem->surface()->frameStarted(); +} + +void Vsp2Layer::handleSurfaceChanged() +{ + auto newSurface = m_hwLayer->waylandItem()->surface(); + + if (Q_UNLIKELY(newSurface == m_surface)) + return; + + if (this->m_surface) + disconnect(this->m_surface, &QWaylandSurface::redraw, this, &Vsp2Layer::handleBufferCommitted); + if (newSurface) + connect(newSurface, &QWaylandSurface::redraw, this, &Vsp2Layer::handleBufferCommitted, Qt::DirectConnection); + + this->m_surface = newSurface; +} + +void Vsp2Layer::updatePosition() +{ + QWaylandQuickItem *wlItem = m_hwLayer->waylandItem(); + QRectF localGeometry(0, 0, wlItem->width(), wlItem->height()); + auto lastMatrix = QWaylandQuickItemPrivate::get(wlItem)->lastMatrix; + auto globalGeometry = lastMatrix.mapRect(localGeometry); + + if (m_buffer.size != globalGeometry.size().toSize()) { + qWarning() << "wl_buffer size != WaylandQuickItem size and scaling has not been" + << "implemented for the vsp2 hardware layer integration"; + } + + m_position = globalGeometry.topLeft().toPoint(); + if (isEnabled()) + QEglFSFunctions::vsp2SetLayerPosition(m_screen, m_layerIndex, m_position); +} + +void Vsp2Layer::updateOpacity() +{ + if (isEnabled()) { + qreal opacity = m_hwLayer->waylandItem()->opacity(); + QEglFSFunctions::vsp2SetLayerAlpha(m_screen, m_layerIndex, opacity); + } +} + +wl_kms_buffer *Vsp2Layer::nextKmsBuffer() +{ + Q_ASSERT(m_hwLayer && m_hwLayer->waylandItem()); + QWaylandQuickItem *wlItem = m_hwLayer->waylandItem(); + auto view = wlItem->view(); + Q_ASSERT(view); + + view->advance(); + auto wlBuffer = view->currentBuffer().wl_buffer(); + + if (!wlBuffer) + return nullptr; + + struct wl_kms_buffer *kmsBuffer = wayland_kms_buffer_get(wlBuffer); + + if (!kmsBuffer) + qWarning() << "Failed to get wl_kms_buffer for wl_buffer:" << wlBuffer->object.id; + + return kmsBuffer; +} + +void Vsp2HardwareLayerIntegration::enableVspLayers() +{ + for (auto &layer : qAsConst(m_layers)) { + Q_ASSERT(!layer->isEnabled()); + layer->enableVspLayer(); + } +} + +void Vsp2HardwareLayerIntegration::disableVspLayers() +{ + for (auto it = m_layers.rbegin(); it != m_layers.rend(); ++it) { + if ((*it)->isEnabled()) + (*it)->disableVspLayer(); + } +} + +void Vsp2HardwareLayerIntegration::sortLayersByDepth() +{ + std::sort(m_layers.begin(), m_layers.end(), [](auto &l1, auto &l2){ + return l1->hwLayer()->stackingLevel() < l2->hwLayer()->stackingLevel(); + }); +} + +void Vsp2HardwareLayerIntegration::recreateVspLayers() { + disableVspLayers(); + sortLayersByDepth(); + enableVspLayers(); +} + +Vsp2HardwareLayerIntegration::Vsp2HardwareLayerIntegration() +{ + if (QGuiApplication::platformName() != "eglfs") { + qWarning() << "Vsp2 layers are currently only supported on the eglfs platform plugin" + << "with the eglfs_kms_vsp2 device integration.\n" + << "You need to set QT_QPA_PLATFORM=eglfs and QT_QPA_EGLFS_INTEGRATION=eglfs_kms_vsp2"; + } + static Vsp2HardwareLayerIntegration *s_instance = this; + QEglFSFunctions::vsp2AddBlendListener(QGuiApplication::primaryScreen(), [](){ + s_instance->sendFrameCallbacks(); + }); +} + +void Vsp2HardwareLayerIntegration::add(QWaylandQuickHardwareLayer *hwLayer) +{ + disableVspLayers(); + m_layers.append(QSharedPointer<Vsp2Layer>(new Vsp2Layer(hwLayer, this))); + sortLayersByDepth(); + enableVspLayers(); +} + +void Vsp2HardwareLayerIntegration::remove(QWaylandQuickHardwareLayer *hwLayer) +{ + disableVspLayers(); + for (auto it = m_layers.begin(); it != m_layers.end(); ++it) { + if ((*it)->hwLayer() == hwLayer) { + m_layers.erase(it); + break; + } + } + enableVspLayers(); +} + +void Vsp2HardwareLayerIntegration::sendFrameCallbacks() +{ + for (auto &layer : qAsConst(m_layers)) { + if (auto *surface = layer->hwLayer()->waylandItem()->surface()) + surface->sendFrameCallbacks(); + } +} + +QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2hardwarelayerintegration.h b/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2hardwarelayerintegration.h new file mode 100644 index 00000000..c9b69b7b --- /dev/null +++ b/src/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2hardwarelayerintegration.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VSP2HARDWARELAYERINTEGRATION_H +#define VSP2HARDWARELAYERINTEGRATION_H + +#include <QtWaylandCompositor/private/qwlhardwarelayerintegration_p.h> +#include <private/qobject_p.h> + +#include <QPoint> +#include <QSize> + +struct wl_kms_buffer; + +QT_BEGIN_NAMESPACE + +class QScreen; +class QWaylandSurface; +class QWaylandQuickHardwareLayer; + +class Vsp2Layer; + +class Vsp2HardwareLayerIntegration : public QtWayland::HardwareLayerIntegration +{ + Q_OBJECT +public: + explicit Vsp2HardwareLayerIntegration(); + + void add(QWaylandQuickHardwareLayer *layer) override; + void remove(QWaylandQuickHardwareLayer *layer) override; + + void sendFrameCallbacks(); + QVector<QSharedPointer<Vsp2Layer>> m_layers; +private: + void enableVspLayers(); + void disableVspLayers(); + void sortLayersByDepth(); + void recreateVspLayers(); + friend class Vsp2Layer; +}; + +struct Vsp2Buffer +{ + explicit Vsp2Buffer() = default; + explicit Vsp2Buffer(wl_kms_buffer *kmsBuffer); + + int dmabufFd = -1; + uint bytesPerLine = 0; + uint drmPixelFormat = 0; + QSize size; +}; + +class Vsp2Layer : public QObject +{ + Q_OBJECT +public: + explicit Vsp2Layer(QWaylandQuickHardwareLayer *m_hwLayer, Vsp2HardwareLayerIntegration *integration); + void enableVspLayer(); + void disableVspLayer(); + bool isEnabled() { return m_layerIndex != -1; } + QWaylandQuickHardwareLayer *hwLayer() const { return m_hwLayer; } + +public slots: + void handleBufferCommitted(); + void handleSurfaceChanged(); + void updatePosition(); + void updateOpacity(); + +private: + wl_kms_buffer *nextKmsBuffer(); + int m_layerIndex = -1; + QScreen *m_screen = nullptr; + QPoint m_position; + QWaylandQuickHardwareLayer *m_hwLayer = nullptr; + QWaylandSurface *m_surface = nullptr; + Vsp2Buffer m_buffer; +}; + +QT_END_NAMESPACE + +#endif // VSP2HARDWARELAYERINTEGRATION_H diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp index 0d6dbf78..44413414 100644 --- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp +++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp @@ -44,6 +44,7 @@ #include <QtWaylandCompositor/QWaylandQuickCompositor> #include <QtWaylandCompositor/QWaylandQuickItem> +#include <QtWaylandCompositor/private/qwaylandquickhardwarelayer_p.h> #include <QtWaylandCompositor/QWaylandQuickSurface> #include <QtWaylandCompositor/QWaylandClient> #include <QtWaylandCompositor/QWaylandQuickOutput> @@ -125,6 +126,7 @@ public: { qmlRegisterType<QWaylandQuickCompositorQuickExtensionContainer>(uri, 1, 0, "WaylandCompositor"); qmlRegisterType<QWaylandQuickItem>(uri, 1, 0, "WaylandQuickItem"); + qmlRegisterType<QWaylandQuickHardwareLayer>(uri, 1, 2, "WaylandHardwareLayer"); qmlRegisterType<QWaylandMouseTracker>(uri, 1, 0, "WaylandMouseTracker"); qmlRegisterType<QWaylandQuickOutput>(uri, 1, 0, "WaylandOutput"); qmlRegisterType<QWaylandQuickSurface>(uri, 1, 0, "WaylandSurface"); diff --git a/src/plugins/hardwareintegration/compositor/compositor.pro b/src/plugins/hardwareintegration/compositor/compositor.pro index 0b2a4292..22301d07 100644 --- a/src/plugins/hardwareintegration/compositor/compositor.pro +++ b/src/plugins/hardwareintegration/compositor/compositor.pro @@ -16,3 +16,5 @@ qtConfig(libhybris-egl-server): \ ### TODO: make shm-emulation configurable SUBDIRS += shm-emulation-server + +SUBDIRS += hardwarelayer diff --git a/src/plugins/hardwareintegration/compositor/hardwarelayer/hardwarelayer.pro b/src/plugins/hardwareintegration/compositor/hardwarelayer/hardwarelayer.pro new file mode 100644 index 00000000..634447af --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/hardwarelayer/hardwarelayer.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs +QT_FOR_CONFIG += waylandcompositor-private + +qtConfig(wayland-layer-integration-vsp2): \ + SUBDIRS += vsp2 diff --git a/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/main.cpp b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/main.cpp new file mode 100644 index 00000000..865637c5 --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/main.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtWaylandCompositor/private/qwlhardwarelayerintegrationplugin_p.h> +#include "vsp2hardwarelayerintegration.h" + +QT_BEGIN_NAMESPACE + +class Vsp2HardwareLayerIntegrationPlugin : public QtWayland::HardwareLayerIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QtWaylandHardwareLayerIntegrationFactoryInterface_iid FILE "vsp2.json") +public: + QtWayland::HardwareLayerIntegration *create(const QString&, const QStringList&) override; +}; + +QtWayland::HardwareLayerIntegration *Vsp2HardwareLayerIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + Q_UNUSED(system); + return new Vsp2HardwareLayerIntegration(); +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.json b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.json new file mode 100644 index 00000000..1fc35bc5 --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "vsp2" ] +} diff --git a/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro new file mode 100644 index 00000000..ff16b20b --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pro @@ -0,0 +1,14 @@ +QT = waylandcompositor waylandcompositor-private core-private gui-private + +QMAKE_USE_PRIVATE += wayland-kms + +OTHER_FILES += vsp2.json + +SOURCES += \ + main.cpp + +include($PWD/../../../../../../hardwareintegration/compositor/hardwarelayer/vsp2/vsp2.pri) + +PLUGIN_TYPE = wayland-hardware-layer-integration +PLUGIN_CLASS_NAME = Vsp2HardwareLayerIntegrationPlugin +load(qt_plugin) |