diff options
author | Paul Olav Tvete <paul.tvete@qt.io> | 2019-01-21 09:25:32 +0100 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@qt.io> | 2019-01-21 09:25:32 +0100 |
commit | 5f645af22bb63f0d215294535cf683029ed7aab5 (patch) | |
tree | 04010e754bbcb70577cee5f396083d0333fe7b4c | |
parent | 9fbaa5c13cfb9712273586abbb708eff07df60a5 (diff) | |
parent | d296dea131ad51cfb4809e9a5e2d6908b2844a57 (diff) | |
download | qtwayland-5f645af22bb63f0d215294535cf683029ed7aab5.tar.gz |
Merge remote-tracking branch 'qt/5.12.1' into 5.12
Change-Id: I6ca92b605c55b0c8941d42e40fad624f00a65cd3
17 files changed, 909 insertions, 106 deletions
diff --git a/dist/changes-5.12.1 b/dist/changes-5.12.1 new file mode 100644 index 00000000..60ca27e9 --- /dev/null +++ b/dist/changes-5.12.1 @@ -0,0 +1,40 @@ +Qt 5.12.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Compositor * +**************************************************************************** + + - [QTBUG-71697] Added a new hardware-integration supporting eglstreams on + NVIDIA platforms. It can be enabled by setting + QT_WAYLAND_CLIENT_BUFFER_INTEGRATION=wayland-eglstream-controller in the + environment. This fixes showing a black frame when resizing client windows. + In addition some flickering problems got fixed, which happened when + the client repainted very often or running without window decorations. + +**************************************************************************** +* QPA plugin * +**************************************************************************** + + - [QTBUG-71734] Fixed a protocol error that used to happen when closing a menu + with an active tooltip. + - [QTBUG-72235] Fixed a crash caused by compositors sending incorrect pointer + events. + - [QTBUG-72818] Fixed a bug where surface damage for window decorations was + outside the surface. diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json index e5bf91e1..7881e6b0 100644 --- a/src/3rdparty/protocol/qt_attribution.json +++ b/src/3rdparty/protocol/qt_attribution.json @@ -103,5 +103,20 @@ Copyright © 2010-2013 Intel Corporation" "LicenseFile": "HPND_LICENSE.txt", "Copyright": "Copyright © 2012, 2013 Intel Corporation Copyright © 2015, 2016 Jan Arne Petersen" - } + }, + + { + "Id": "wayland-eglstream-controller", + "Name": "Wayland EGLStream Controller Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland Compositor", + "Files": "wayland-eglstream-controller.xml", + + "Description": "Allows clients to request that the compositor creates its EGLStream.", + "Homepage": "https://github.com/NVIDIA/egl-wayland", + "LicenseId": "MIT", + "License": "MIT License", + "LicenseFile": "MIT_LICENSE.txt", + "Copyright": "Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved." + } ] diff --git a/src/3rdparty/protocol/wl-eglstream-controller.xml b/src/3rdparty/protocol/wl-eglstream-controller.xml new file mode 100644 index 00000000..dea072e6 --- /dev/null +++ b/src/3rdparty/protocol/wl-eglstream-controller.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="wl_eglstream_controller"> + <copyright> + Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> + <interface name="wl_eglstream_controller" version="1"> + <request name="attach_eglstream_consumer"> + <description summary="Create server stream and attach consumer"> + Creates the corresponding server side EGLStream from the given wl_buffer + and attaches a consumer to it. + </description> + <arg name="wl_surface" type="object" interface="wl_surface" + summary="wl_surface corresponds to the client surface associated with + newly created eglstream"/> + <arg name="wl_resource" type="object" interface="wl_buffer" + summary="wl_resource corresponding to an EGLStream"/> + </request> + </interface> +</protocol> diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index e935ef31..97e0203c 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -339,6 +339,8 @@ void QWaylandIntegration::initializeClientBufferIntegration() targetKey = QString::fromLocal8Bit(clientBufferIntegrationName); } else { targetKey = mDisplay->hardwareIntegration()->clientBufferIntegration(); + if (targetKey == QLatin1String("wayland-eglstream-controller")) + targetKey = QLatin1String("wayland-egl"); } if (targetKey.isEmpty()) { diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 470ae009..282179ef 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -358,8 +358,6 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect) { if (!(mShellSurface && mShellSurface->handleExpose(rect))) QWindowSystemInterface::handleExposeEvent(window(), rect); - else - qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending"; mLastExposeGeometry = rect; } @@ -544,11 +542,18 @@ void QWaylandWindow::handleScreenRemoved(QScreen *qScreen) void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) { Q_ASSERT(!buffer->committed()); + if (mFrameCallback) { + wl_callback_destroy(mFrameCallback); + mFrameCallback = nullptr; + } + if (buffer) { - handleUpdate(); + mFrameCallback = frame(); + wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); + mWaitingForFrameSync = true; buffer->setBusy(); - QtWayland::wl_surface::attach(buffer->buffer(), x, y); + attach(buffer->buffer(), x, y); } else { QtWayland::wl_surface::attach(nullptr, 0, 0); } @@ -613,9 +618,11 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uin Q_UNUSED(callback); QWaylandWindow *self = static_cast<QWaylandWindow*>(data); - self->mWaitingForFrameCallback = false; - if (self->mUpdateRequested) + self->mWaitingForFrameSync = false; + if (self->mUpdateRequested) { + self->mUpdateRequested = false; self->deliverUpdateRequest(); + } } QMutex QWaylandWindow::mFrameSyncMutex; @@ -623,10 +630,10 @@ QMutex QWaylandWindow::mFrameSyncMutex; void QWaylandWindow::waitForFrameSync() { QMutexLocker locker(&mFrameSyncMutex); - if (!mWaitingForFrameCallback) + if (!mWaitingForFrameSync) return; mDisplay->flushRequests(); - while (mWaitingForFrameCallback) + while (mWaitingForFrameSync) mDisplay->blockingReadEvents(); } @@ -1027,88 +1034,12 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa return m_properties.value(name, defaultValue); } -void QWaylandWindow::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == mFallbackUpdateTimerId) { - killTimer(mFallbackUpdateTimerId); - mFallbackUpdateTimerId = -1; - - if (!isExposed()) { - qCDebug(lcWaylandBackingstore) << "Fallback update timer: Window not exposed," - << "not delivering update request."; - return; - } - - if (mWaitingForUpdate && mUpdateRequested && !mWaitingForFrameCallback) { - qCWarning(lcWaylandBackingstore) << "Delivering update request through fallback timer," - << "may not be in sync with display"; - deliverUpdateRequest(); - } - } -} - void QWaylandWindow::requestUpdate() { - if (mUpdateRequested) - return; - - mUpdateRequested = true; - - // If we have a frame callback all is good and will be taken care of there - if (mWaitingForFrameCallback) - return; - - // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet - if (mWaitingForUpdate) { - // Ideally, we should just have returned here, but we're not guaranteed that the client - // will actually update, so start this timer to deliver another request update after a while - // *IF* the client doesn't update. - int fallbackTimeout = 100; - mFallbackUpdateTimerId = startTimer(fallbackTimeout); - return; - } - - // Some applications (such as Qt Quick) depend on updates being delivered asynchronously, - // so use invokeMethod to delay the delivery a bit. - QMetaObject::invokeMethod(this, [this] { - // Things might have changed in the meantime - if (mUpdateRequested && !mWaitingForUpdate && !mWaitingForFrameCallback) - deliverUpdateRequest(); - }, Qt::QueuedConnection); -} - -// Should be called whenever we commit a buffer (directly through wl_surface.commit or indirectly -// with eglSwapBuffers) to know when it's time to commit the next one. -// Can be called from the render thread (without locking anything) so make sure to not make races in this method. -void QWaylandWindow::handleUpdate() -{ - // TODO: Should sync subsurfaces avoid requesting frame callbacks? - - if (mFrameCallback) { - wl_callback_destroy(mFrameCallback); - mFrameCallback = nullptr; - } - - if (mFallbackUpdateTimerId != -1) { - // Ideally, we would stop the fallback timer here, but since we're on another thread, - // it's not allowed. Instead we set mFallbackUpdateTimer to -1 here, so we'll just - // ignore it if it times out before it's cleaned up by the invokeMethod call. - int id = mFallbackUpdateTimerId; - mFallbackUpdateTimerId = -1; - QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); - } - - mFrameCallback = frame(); - wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); - mWaitingForFrameCallback = true; - mWaitingForUpdate = false; -} - -void QWaylandWindow::deliverUpdateRequest() -{ - mUpdateRequested = false; - mWaitingForUpdate = true; - QPlatformWindow::deliverUpdateRequest(); + if (!mWaitingForFrameSync) + QPlatformWindow::requestUpdate(); + else + mUpdateRequested = true; } void QWaylandWindow::addAttachOffset(const QPoint point) diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index e5838d23..56ebd3cc 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -191,10 +191,7 @@ public: bool startSystemMove(const QPoint &pos) override; - void timerEvent(QTimerEvent *event) override; void requestUpdate() override; - void handleUpdate(); - void deliverUpdateRequest() override; public slots: void applyConfigure(); @@ -214,14 +211,10 @@ protected: Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton; WId mWindowId; - bool mWaitingForFrameCallback = false; + bool mWaitingForFrameSync = false; struct ::wl_callback *mFrameCallback = nullptr; QWaitCondition mFrameSyncWait; - // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer - bool mWaitingForUpdate = false; - int mFallbackUpdateTimerId = -1; - QMutex mResizeLock; bool mWaitingToApplyConfigure = false; bool mCanResize = true; diff --git a/src/compositor/compositor_api/qwaylandquickoutput.cpp b/src/compositor/compositor_api/qwaylandquickoutput.cpp index 79e4fdec..c6294eea 100644 --- a/src/compositor/compositor_api/qwaylandquickoutput.cpp +++ b/src/compositor/compositor_api/qwaylandquickoutput.cpp @@ -66,7 +66,7 @@ void QWaylandQuickOutput::initialize() this, &QWaylandQuickOutput::updateStarted, Qt::DirectConnection); - connect(quickWindow, &QQuickWindow::beforeRendering, + connect(quickWindow, &QQuickWindow::afterRendering, this, &QWaylandQuickOutput::doFrameCallbacks); } diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index 0cbbe538..a8ee9a43 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -315,9 +315,7 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis mSupportNonBlockingSwap = false; } if (!mSupportNonBlockingSwap) { - qWarning(lcQpaWayland) << "Non-blocking swap buffers not supported." - << "Subsurface rendering can be affected." - << "It may also cause the event loop to freeze in some situations"; + qWarning() << "Non-blocking swap buffers not supported. Subsurface rendering can be affected."; } updateGLFormat(); @@ -401,8 +399,13 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface); EGLSurface eglSurface = window->eglSurface(); - if (!window->needToUpdateContentFBO() && (eglSurface != EGL_NO_SURFACE && eglGetCurrentContext() == m_context && eglGetCurrentSurface(EGL_DRAW) == eglSurface)) + if (!window->needToUpdateContentFBO() && (eglSurface != EGL_NO_SURFACE)) { + if (!eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context)) { + qWarning("QWaylandGLContext::makeCurrent: eglError: %x, this: %p \n", eglGetError(), this); + return false; + } return true; + } if (window->isExposed()) window->setCanResize(false); @@ -552,10 +555,20 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) m_blitter->blit(window); } - window->handleUpdate(); - int swapInterval = mSupportNonBlockingSwap ? 0 : m_format.swapInterval(); - eglSwapInterval(m_eglDisplay, swapInterval); - eglSwapBuffers(m_eglDisplay, eglSurface); + + QWaylandSubSurface *sub = window->subSurfaceWindow(); + if (sub) { + QMutexLocker l(sub->syncMutex()); + + int si = (sub->isSync() && mSupportNonBlockingSwap) ? 0 : m_format.swapInterval(); + + eglSwapInterval(m_eglDisplay, si); + eglSwapBuffers(m_eglDisplay, eglSurface); + } else { + eglSwapInterval(m_eglDisplay, m_format.swapInterval()); + eglSwapBuffers(m_eglDisplay, eglSurface); + } + window->setCanResize(true); } diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pri b/src/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pri new file mode 100644 index 00000000..931475ef --- /dev/null +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pri @@ -0,0 +1,16 @@ +INCLUDEPATH += $$PWD + +QMAKE_USE_PRIVATE += egl wayland-server wayland-egl + +CONFIG += wayland-scanner +WAYLANDSERVERSOURCES += $$PWD/../../../3rdparty/protocol/wl-eglstream-controller.xml + +QT += egl_support-private + +SOURCES += \ + $$PWD/waylandeglstreamintegration.cpp \ + $$PWD/waylandeglstreamcontroller.cpp + +HEADERS += \ + $$PWD/waylandeglstreamintegration.h \ + $$PWD/waylandeglstreamcontroller.h diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamcontroller.cpp b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamcontroller.cpp new file mode 100644 index 00000000..09859d7e --- /dev/null +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamcontroller.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "waylandeglstreamcontroller.h" +#include "waylandeglstreamintegration.h" + +#include <QtWaylandCompositor/QWaylandCompositor> + +#include <unistd.h> + +QT_BEGIN_NAMESPACE + + + +WaylandEglStreamController::WaylandEglStreamController(wl_display *display, WaylandEglStreamClientBufferIntegration *clientBufferIntegration) + : wl_eglstream_controller(display, 1 /*version*/) + , m_clientBufferIntegration(clientBufferIntegration) +{ +} + +void WaylandEglStreamController::eglstream_controller_attach_eglstream_consumer(Resource *resource, struct ::wl_resource *wl_surface, struct ::wl_resource *wl_buffer) +{ + Q_UNUSED(resource); + m_clientBufferIntegration->attachEglStreamConsumer(wl_surface, wl_buffer); +} + +QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamcontroller.h b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamcontroller.h new file mode 100644 index 00000000..3a7fcee7 --- /dev/null +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamcontroller.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 WAYLANDEGLSTREAMCONTROLLER_H +#define WAYLANDEGLSTREAMCONTROLLER_H + +#include "qwayland-server-wl-eglstream-controller.h" + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> +#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> + +#include <QtCore/QObject> +#include <QtCore/QHash> +#include <QtCore/QSize> +#include <QtCore/QTextStream> +#include <QtGui/QOpenGLTexture> + +#include <EGL/egl.h> +#include <EGL/eglext.h> + + +QT_BEGIN_NAMESPACE + +class QWaylandCompositor; +class QWaylandResource; +class WaylandEglStreamClientBufferIntegration; + +class WaylandEglStreamController : public QtWaylandServer::wl_eglstream_controller +{ +public: + explicit WaylandEglStreamController(wl_display *display, WaylandEglStreamClientBufferIntegration *clientBufferIntegration); + +protected: + void eglstream_controller_attach_eglstream_consumer(Resource *resource, struct ::wl_resource *wl_surface, struct ::wl_resource *wl_buffer) override; + +private: + WaylandEglStreamClientBufferIntegration *m_clientBufferIntegration; +}; + + +QT_END_NAMESPACE + +#endif // WAYLANDEGLSTREAMCONTROLLER_H diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp new file mode 100644 index 00000000..1493e9fc --- /dev/null +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp @@ -0,0 +1,439 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "waylandeglstreamintegration.h" +#include "waylandeglstreamcontroller.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtGui/QGuiApplication> +#include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLTexture> +#include <QtGui/QOffscreenSurface> + +#include <QtEglSupport/private/qeglstreamconvenience_p.h> +#include <qpa/qplatformnativeinterface.h> + +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwlbuffermanager_p.h> + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <unistd.h> + +#ifndef GL_TEXTURE_EXTERNAL_OES +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#endif + +#ifndef EGL_WAYLAND_BUFFER_WL +#define EGL_WAYLAND_BUFFER_WL 0x31D5 +#endif + +#ifndef EGL_WAYLAND_EGLSTREAM_WL +#define EGL_WAYLAND_EGLSTREAM_WL 0x334B +#endif + +#ifndef EGL_WAYLAND_PLANE_WL +#define EGL_WAYLAND_PLANE_WL 0x31D6 +#endif + +#ifndef EGL_WAYLAND_Y_INVERTED_WL +#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB +#endif + +#ifndef EGL_TEXTURE_RGB +#define EGL_TEXTURE_RGB 0x305D +#endif + +#ifndef EGL_TEXTURE_RGBA +#define EGL_TEXTURE_RGBA 0x305E +#endif + +#ifndef EGL_TEXTURE_EXTERNAL_WL +#define EGL_TEXTURE_EXTERNAL_WL 0x31DA +#endif + +#ifndef EGL_TEXTURE_Y_U_V_WL +#define EGL_TEXTURE_Y_U_V_WL 0x31D7 +#endif + +#ifndef EGL_TEXTURE_Y_UV_WL +#define EGL_TEXTURE_Y_UV_WL 0x31D8 +#endif + +#ifndef EGL_TEXTURE_Y_XUXV_WL +#define EGL_TEXTURE_Y_XUXV_WL 0x31D9 +#endif + +#ifndef EGL_PLATFORM_X11_KHR +#define EGL_PLATFORM_X11_KHR 0x31D5 +#endif + +QT_BEGIN_NAMESPACE + +/* Needed for compatibility with Mesa older than 10.0. */ +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL_compat) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); + +#ifndef EGL_WL_bind_wayland_display +typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); +#endif + +static const char * +egl_error_string(EGLint code) +{ +#define MYERRCODE(x) case x: return #x; + switch (code) { + MYERRCODE(EGL_SUCCESS) + MYERRCODE(EGL_NOT_INITIALIZED) + MYERRCODE(EGL_BAD_ACCESS) + MYERRCODE(EGL_BAD_ALLOC) + MYERRCODE(EGL_BAD_ATTRIBUTE) + MYERRCODE(EGL_BAD_CONTEXT) + MYERRCODE(EGL_BAD_CONFIG) + MYERRCODE(EGL_BAD_CURRENT_SURFACE) + MYERRCODE(EGL_BAD_DISPLAY) + MYERRCODE(EGL_BAD_SURFACE) + MYERRCODE(EGL_BAD_MATCH) + MYERRCODE(EGL_BAD_PARAMETER) + MYERRCODE(EGL_BAD_NATIVE_PIXMAP) + MYERRCODE(EGL_BAD_NATIVE_WINDOW) + MYERRCODE(EGL_CONTEXT_LOST) + default: + return "unknown"; + } +#undef MYERRCODE +} + +struct BufferState +{ + BufferState() = default; + + EGLint egl_format = EGL_TEXTURE_EXTERNAL_WL; + QOpenGLTexture *textures[3] = {}; + EGLStreamKHR egl_stream = EGL_NO_STREAM_KHR; + + bool isYInverted = false; + QSize size; +}; + +class WaylandEglStreamClientBufferIntegrationPrivate +{ +public: + WaylandEglStreamClientBufferIntegrationPrivate() = default; + + bool ensureContext(); + bool initEglStream(WaylandEglStreamClientBuffer *buffer, struct ::wl_resource *bufferHandle); + void handleEglstreamTexture(WaylandEglStreamClientBuffer *buffer); + void deleteGLTextureWhenPossible(QOpenGLTexture *texture) { orphanedTextures << texture; } + void deleteOrphanedTextures(); + + EGLDisplay egl_display = EGL_NO_DISPLAY; + bool display_bound = false; + QOffscreenSurface *offscreenSurface = nullptr; + QOpenGLContext *localContext = nullptr; + QVector<QOpenGLTexture *> orphanedTextures; + + WaylandEglStreamController *eglStreamController = nullptr; + + PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display = nullptr; + PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display = nullptr; + PFNEGLQUERYWAYLANDBUFFERWL_compat egl_query_wayland_buffer = nullptr; + + QEGLStreamConvenience *funcs = nullptr; + static WaylandEglStreamClientBufferIntegrationPrivate *get(WaylandEglStreamClientBufferIntegration *integration) { + return shuttingDown ? nullptr : integration->d_ptr.data(); + } + + static bool shuttingDown; +}; + +bool WaylandEglStreamClientBufferIntegrationPrivate::shuttingDown = false; + +void WaylandEglStreamClientBufferIntegrationPrivate::deleteOrphanedTextures() +{ + Q_ASSERT(QOpenGLContext::currentContext()); + qDeleteAll(orphanedTextures); + orphanedTextures.clear(); +} + +bool WaylandEglStreamClientBufferIntegrationPrivate::ensureContext() +{ + bool localContextNeeded = false; + if (!QOpenGLContext::currentContext()) { + if (!localContext && QOpenGLContext::globalShareContext()) { + localContext = new QOpenGLContext; + localContext->setShareContext(QOpenGLContext::globalShareContext()); + localContext->create(); + } + if (localContext) { + if (!offscreenSurface) { + offscreenSurface = new QOffscreenSurface; + offscreenSurface->setFormat(localContext->format()); + offscreenSurface->create(); + } + localContext->makeCurrent(offscreenSurface); + localContextNeeded = true; + } + } + return localContextNeeded; +} + + +bool WaylandEglStreamClientBufferIntegrationPrivate::initEglStream(WaylandEglStreamClientBuffer *buffer, wl_resource *bufferHandle) +{ + BufferState &state = *buffer->d; + state.egl_format = EGL_TEXTURE_EXTERNAL_WL; + state.isYInverted = false; + + EGLNativeFileDescriptorKHR streamFd = EGL_NO_FILE_DESCRIPTOR_KHR; + + if (egl_query_wayland_buffer(egl_display, bufferHandle, EGL_WAYLAND_BUFFER_WL, &streamFd)) { + state.egl_stream = funcs->create_stream_from_file_descriptor(egl_display, streamFd); + close(streamFd); + } else { + EGLAttrib stream_attribs[] = { + EGL_WAYLAND_EGLSTREAM_WL, (EGLAttrib)bufferHandle, + EGL_NONE + }; + state.egl_stream = funcs->create_stream_attrib_nv(egl_display, stream_attribs); + } + + if (state.egl_stream == EGL_NO_STREAM_KHR) { + qWarning("%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError()); + return false; + } + + bool usingLocalContext = ensureContext(); + + Q_ASSERT(QOpenGLContext::currentContext()); + + auto texture = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(GL_TEXTURE_EXTERNAL_OES)); + texture->create(); + state.textures[0] = texture; // TODO: support multiple planes + + texture->bind(); + + auto newStream = funcs->stream_consumer_gltexture(egl_display, state.egl_stream); + if (usingLocalContext) + localContext->doneCurrent(); + + if (!newStream) { + EGLint code = eglGetError(); + qWarning() << "Could not initialize EGLStream:" << egl_error_string(code) << hex << (long)code; + funcs->destroy_stream(egl_display, state.egl_stream); + state.egl_stream = EGL_NO_STREAM_KHR; + return false; + } + return true; +} + +void WaylandEglStreamClientBufferIntegrationPrivate::handleEglstreamTexture(WaylandEglStreamClientBuffer *buffer) +{ + bool usingLocalContext = ensureContext(); + + BufferState &state = *buffer->d; + auto texture = state.textures[0]; + + // EGLStream requires calling acquire on every frame. + texture->bind(); + EGLint stream_state; + funcs->query_stream(egl_display, state.egl_stream, EGL_STREAM_STATE_KHR, &stream_state); + + if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) { + if (funcs->stream_consumer_acquire(egl_display, state.egl_stream) != EGL_TRUE) + qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError()); + } + + if (usingLocalContext) + localContext->doneCurrent(); +} + + +WaylandEglStreamClientBufferIntegration::WaylandEglStreamClientBufferIntegration() + : d_ptr(new WaylandEglStreamClientBufferIntegrationPrivate) +{ +} + +WaylandEglStreamClientBufferIntegration::~WaylandEglStreamClientBufferIntegration() +{ + WaylandEglStreamClientBufferIntegrationPrivate::shuttingDown = true; +} + +void WaylandEglStreamClientBufferIntegration::attachEglStreamConsumer(struct ::wl_resource *wl_surface, struct ::wl_resource *wl_buffer) +{ + Q_D(WaylandEglStreamClientBufferIntegration); + Q_UNUSED(wl_surface); + + // NOTE: must use getBuffer to create the buffer here, so the buffer will end up in the buffer manager's hash + + auto *bufferManager = QWaylandCompositorPrivate::get(m_compositor)->bufferManager(); + auto *clientBuffer = static_cast<WaylandEglStreamClientBuffer*>(bufferManager->getBuffer(wl_buffer)); + + d->initEglStream(clientBuffer, wl_buffer); +} + +void WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_display *display) +{ + Q_D(WaylandEglStreamClientBufferIntegration); + + const bool ignoreBindDisplay = !qgetenv("QT_WAYLAND_IGNORE_BIND_DISPLAY").isEmpty(); + + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + if (!nativeInterface) { + qWarning("QtCompositor: Failed to initialize EGL display. No native platform interface available."); + return; + } + + d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); + if (!d->egl_display) { + qWarning("QtCompositor: Failed to initialize EGL display. Could not get EglDisplay for window."); + return; + } + + const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS); + if ((!extensionString || !strstr(extensionString, "EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) { + qWarning("QtCompositor: Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension."); + return; + } + + d->egl_bind_wayland_display = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL")); + d->egl_unbind_wayland_display = reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL")); + if ((!d->egl_bind_wayland_display || !d->egl_unbind_wayland_display) && !ignoreBindDisplay) { + qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."); + return; + } + + d->egl_query_wayland_buffer = reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL_compat>(eglGetProcAddress("eglQueryWaylandBufferWL")); + if (!d->egl_query_wayland_buffer) { + qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL."); + return; + } + + if (d->egl_bind_wayland_display && d->egl_unbind_wayland_display) { + d->display_bound = d->egl_bind_wayland_display(d->egl_display, display); + if (!d->display_bound) { + if (!ignoreBindDisplay) { + qWarning("QtCompositor: Failed to initialize EGL display. Could not bind Wayland display."); + return; + } else { + qWarning("QtCompositor: Could not bind Wayland display. Ignoring."); + } + } + } + + d->eglStreamController = new WaylandEglStreamController(display, this); + + d->funcs = new QEGLStreamConvenience; + d->funcs->initialize(d->egl_display); +} + +QtWayland::ClientBuffer *WaylandEglStreamClientBufferIntegration::createBufferFor(wl_resource *buffer) +{ + if (wl_shm_buffer_get(buffer)) + return nullptr; + + return new WaylandEglStreamClientBuffer(this, buffer); +} + + +WaylandEglStreamClientBuffer::WaylandEglStreamClientBuffer(WaylandEglStreamClientBufferIntegration *integration, wl_resource *buffer) + : ClientBuffer(buffer) + , m_integration(integration) +{ + auto *p = WaylandEglStreamClientBufferIntegrationPrivate::get(m_integration); + d = new BufferState; + if (buffer && !wl_shm_buffer_get(buffer)) { + EGLint width, height; + p->egl_query_wayland_buffer(p->egl_display, buffer, EGL_WIDTH, &width); + p->egl_query_wayland_buffer(p->egl_display, buffer, EGL_HEIGHT, &height); + d->size = QSize(width, height); + } +} + +WaylandEglStreamClientBuffer::~WaylandEglStreamClientBuffer() +{ + auto *p = WaylandEglStreamClientBufferIntegrationPrivate::get(m_integration); + + if (p) { + if (d->egl_stream) + p->funcs->destroy_stream(p->egl_display, d->egl_stream); + + for (auto *texture : d->textures) + p->deleteGLTextureWhenPossible(texture); + } + delete d; +} + + +QWaylandBufferRef::BufferFormatEgl WaylandEglStreamClientBuffer::bufferFormatEgl() const +{ + return QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES; +} + + +QSize WaylandEglStreamClientBuffer::size() const +{ + return d->size; +} + +QWaylandSurface::Origin WaylandEglStreamClientBuffer::origin() const +{ + return d->isYInverted ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft; +} + +QOpenGLTexture *WaylandEglStreamClientBuffer::toOpenGlTexture(int plane) +{ + auto *p = WaylandEglStreamClientBufferIntegrationPrivate::get(m_integration); + // At this point we should have a valid OpenGL context, so it's safe to destroy textures + p->deleteOrphanedTextures(); + + if (!m_buffer) + return nullptr; + + return d->textures[plane]; +} + +void WaylandEglStreamClientBuffer::setCommitted(QRegion &damage) +{ + ClientBuffer::setCommitted(damage); + auto *p = WaylandEglStreamClientBufferIntegrationPrivate::get(m_integration); + p->handleEglstreamTexture(this); +} + +QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h new file mode 100644 index 00000000..d1930204 --- /dev/null +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 WAYLANDEGLSTREAMINTEGRATION_H +#define WAYLANDEGLSTREAMINTEGRATION_H + +#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> +#include <QtCore/QScopedPointer> +#include <QtWaylandCompositor/private/qwlclientbuffer_p.h> + +QT_BEGIN_NAMESPACE + +class WaylandEglStreamClientBufferIntegrationPrivate; + +class WaylandEglStreamClientBufferIntegration : public QtWayland::ClientBufferIntegration +{ + Q_DECLARE_PRIVATE(WaylandEglStreamClientBufferIntegration) +public: + WaylandEglStreamClientBufferIntegration(); + ~WaylandEglStreamClientBufferIntegration() override; + + void initializeHardware(struct ::wl_display *display) override; + + QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; + + void attachEglStreamConsumer(struct ::wl_resource *wl_surface, struct ::wl_resource *wl_buffer); + +private: + Q_DISABLE_COPY(WaylandEglStreamClientBufferIntegration) + QScopedPointer<WaylandEglStreamClientBufferIntegrationPrivate> d_ptr; +}; + +struct BufferState; + +class WaylandEglStreamClientBuffer : public QtWayland::ClientBuffer +{ +public: + ~WaylandEglStreamClientBuffer() override; + + QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const override; + QSize size() const override; + QWaylandSurface::Origin origin() const override; + QOpenGLTexture *toOpenGlTexture(int plane) override; + void setCommitted(QRegion &damage) override; + +private: + friend class WaylandEglStreamClientBufferIntegration; + friend class WaylandEglStreamClientBufferIntegrationPrivate; + + WaylandEglStreamClientBuffer(WaylandEglStreamClientBufferIntegration* integration, wl_resource *bufferResource); + + BufferState *d = nullptr; + WaylandEglStreamClientBufferIntegration *m_integration = nullptr; +}; + +QT_END_NAMESPACE + +#endif // WAYLANDEGLSTREAMINTEGRATION_H diff --git a/src/plugins/hardwareintegration/compositor/compositor.pro b/src/plugins/hardwareintegration/compositor/compositor.pro index cd47b267..66272e83 100644 --- a/src/plugins/hardwareintegration/compositor/compositor.pro +++ b/src/plugins/hardwareintegration/compositor/compositor.pro @@ -19,4 +19,8 @@ qtConfig(wayland-shm-emulation-server-buffer): \ qtConfig(wayland-dmabuf-server-buffer): \ SUBDIRS += dmabuf-server +qtConfig(wayland-egl): \ + SUBDIRS += wayland-eglstream-controller + + SUBDIRS += hardwarelayer diff --git a/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/main.cpp b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/main.cpp new file mode 100644 index 00000000..8e1d5090 --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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/qwlclientbufferintegrationfactory_p.h> +#include <QtWaylandCompositor/private/qwlclientbufferintegrationplugin_p.h> +#include "waylandeglstreamintegration.h" + +QT_BEGIN_NAMESPACE + +class QWaylandEglStreamClientBufferIntegrationPlugin : public QtWayland::ClientBufferIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QtWaylandClientBufferIntegrationFactoryInterface_iid FILE "wayland-eglstream-controller.json") +public: + QtWayland::ClientBufferIntegration *create(const QString& key, const QStringList& paramList) override; +}; + +QtWayland::ClientBufferIntegration *QWaylandEglStreamClientBufferIntegrationPlugin::create(const QString& key, const QStringList& paramList) +{ + Q_UNUSED(paramList); + Q_UNUSED(key); + return new WaylandEglStreamClientBufferIntegration(); +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.json b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.json new file mode 100644 index 00000000..0c94bb77 --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "wayland-eglstream-controller" ] +} diff --git a/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro new file mode 100644 index 00000000..f1ca7183 --- /dev/null +++ b/src/plugins/hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pro @@ -0,0 +1,12 @@ +QT = waylandcompositor waylandcompositor-private core-private gui-private + +OTHER_FILES += wayland-eglstream-controller.json + +SOURCES += \ + main.cpp \ + +include(../../../../hardwareintegration/compositor/wayland-eglstream-controller/wayland-eglstream-controller.pri) + +PLUGIN_TYPE = wayland-graphics-integration-server +PLUGIN_CLASS_NAME = QWaylandEglStreamBufferIntegrationPlugin +load(qt_plugin) |