summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compositor/extensions/extensions.pri8
-rw-r--r--src/compositor/extensions/qwltexturesharingextension.cpp497
-rw-r--r--src/compositor/extensions/qwltexturesharingextension_p.h159
-rw-r--r--src/extensions/qt-texture-sharing-unstable-v1.xml57
-rw-r--r--src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp4
-rw-r--r--src/imports/imports.pro7
-rw-r--r--src/imports/texture-sharing-extension/plugin.cpp109
-rw-r--r--src/imports/texture-sharing-extension/qmldir3
-rw-r--r--src/imports/texture-sharing-extension/texture-sharing-extension.pro11
-rw-r--r--src/imports/texture-sharing/plugin.cpp97
-rw-r--r--src/imports/texture-sharing/qmldir3
-rw-r--r--src/imports/texture-sharing/sharedtextureprovider.cpp322
-rw-r--r--src/imports/texture-sharing/sharedtextureprovider.h118
-rw-r--r--src/imports/texture-sharing/texture-sharing.pro21
-rw-r--r--src/imports/texture-sharing/texturesharingextension.cpp86
-rw-r--r--src/imports/texture-sharing/texturesharingextension.h77
-rw-r--r--src/src.pro2
17 files changed, 1576 insertions, 5 deletions
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri
index 5c708f891..42d99895b 100644
--- a/src/compositor/extensions/extensions.pri
+++ b/src/compositor/extensions/extensions.pri
@@ -8,6 +8,7 @@ WAYLANDSERVERSOURCES += \
../extensions/touch-extension.xml \
../extensions/qt-key-unstable-v1.xml \
../extensions/qt-windowmanager.xml \
+ ../extensions/qt-texture-sharing-unstable-v1.xml \
../3rdparty/protocol/text-input-unstable-v2.xml \
../3rdparty/protocol/xdg-shell-unstable-v6.xml \
../3rdparty/protocol/xdg-shell.xml \
@@ -65,7 +66,8 @@ qtHaveModule(quick):contains(QT_CONFIG, opengl) {
extensions/qwaylandwlshellintegration_p.h \
extensions/qwaylandxdgshellv5integration_p.h \
extensions/qwaylandxdgshellv6integration_p.h \
- extensions/qwaylandxdgshellintegration_p.h
+ extensions/qwaylandxdgshellintegration_p.h \
+ extensions/qwltexturesharingextension_p.h
SOURCES += \
extensions/qwaylandquickshellsurfaceitem.cpp \
@@ -73,8 +75,8 @@ qtHaveModule(quick):contains(QT_CONFIG, opengl) {
extensions/qwaylandwlshellintegration.cpp \
extensions/qwaylandxdgshellv5integration.cpp \
extensions/qwaylandxdgshellv6integration.cpp \
- extensions/qwaylandxdgshellintegration.cpp
-
+ extensions/qwaylandxdgshellintegration.cpp \
+ extensions/qwltexturesharingextension.cpp
}
include ($$PWD/pregenerated/xdg-shell-v5.pri)
diff --git a/src/compositor/extensions/qwltexturesharingextension.cpp b/src/compositor/extensions/qwltexturesharingextension.cpp
new file mode 100644
index 000000000..1c15bb49f
--- /dev/null
+++ b/src/compositor/extensions/qwltexturesharingextension.cpp
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** 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 "qwltexturesharingextension_p.h"
+
+#include <QWaylandSurface>
+
+#include <QDebug>
+
+#include <QQuickWindow>
+
+#include <QPainter>
+#include <QPen>
+#include <QTimer>
+
+#include <QtGui/private/qtexturefilereader_p.h>
+#include <QtGui/QOpenGLTexture>
+#include <QtGui/QImageReader>
+
+#include <QtQuick/QSGTexture>
+#include <QQmlContext>
+#include <QThread>
+
+QT_BEGIN_NAMESPACE
+
+class SharedTexture : public QSGTexture
+{
+ Q_OBJECT
+public:
+ SharedTexture(QtWayland::ServerBuffer *buffer);
+
+ int textureId() const override;
+ QSize textureSize() const override;
+ bool hasAlphaChannel() const override;
+ bool hasMipmaps() const override;
+
+ void bind() override;
+
+private:
+ void updateGLTexture() const;
+ QtWayland::ServerBuffer *m_buffer = nullptr;
+ mutable QOpenGLTexture *m_tex = nullptr;
+};
+
+SharedTexture::SharedTexture(QtWayland::ServerBuffer *buffer)
+ : m_buffer(buffer), m_tex(nullptr)
+{
+}
+
+int SharedTexture::textureId() const
+{
+ updateGLTexture();
+ return m_tex ? m_tex->textureId() : 0;
+}
+
+QSize SharedTexture::textureSize() const
+{
+ updateGLTexture();
+ return m_tex ? QSize(m_tex->width(), m_tex->height()) : QSize();
+}
+
+bool SharedTexture::hasAlphaChannel() const
+{
+ return true;
+}
+
+bool SharedTexture::hasMipmaps() const
+{
+ updateGLTexture();
+ return m_tex ? (m_tex->mipLevels() > 1) : false;
+}
+
+void SharedTexture::bind()
+{
+ updateGLTexture();
+ if (m_tex)
+ m_tex->bind();
+}
+
+inline void SharedTexture::updateGLTexture() const
+{
+ if (!m_tex && m_buffer)
+ m_tex = m_buffer->toOpenGlTexture();
+}
+
+class SharedTextureFactory : public QQuickTextureFactory
+{
+public:
+ SharedTextureFactory(const QtWayland::ServerBuffer *buffer)
+ : m_buffer(buffer)
+ {
+ }
+
+ ~SharedTextureFactory() override
+ {
+ if (m_buffer)
+ const_cast<QtWayland::ServerBuffer*>(m_buffer)->releaseOpenGlTexture();
+ }
+
+ QSize textureSize() const override
+ {
+ return m_buffer ? m_buffer->size() : QSize();
+ }
+
+ int textureByteCount() const override
+ {
+ return m_buffer ? (m_buffer->size().width() * m_buffer->size().height() * 4) : 0;
+ }
+
+ QSGTexture *createTexture(QQuickWindow *) const override
+ {
+ return new SharedTexture(const_cast<QtWayland::ServerBuffer *>(m_buffer));
+ }
+
+private:
+ const QtWayland::ServerBuffer *m_buffer = nullptr;
+};
+
+class SharedTextureImageResponse : public QQuickImageResponse
+{
+ Q_OBJECT
+public:
+ SharedTextureImageResponse(QWaylandTextureSharingExtension *extension, const QString &id)
+ : m_id(id)
+ {
+ if (extension)
+ doRequest(extension);
+ }
+
+ void doRequest(QWaylandTextureSharingExtension *extension)
+ {
+ m_extension = extension;
+ connect(extension, &QWaylandTextureSharingExtension::bufferResult, this, &SharedTextureImageResponse::doResponse);
+ QMetaObject::invokeMethod(extension, [this] { m_extension->requestBuffer(m_id); }, Qt::AutoConnection);
+ }
+
+ QQuickTextureFactory *textureFactory() const override
+ {
+ if (m_buffer) {
+// qDebug() << "Creating shared buffer texture for" << m_id;
+ return new SharedTextureFactory(m_buffer);
+ }
+// qDebug() << "Shared buffer NOT found for" << m_id;
+ m_errorString = QLatin1Literal("Shared buffer not found");
+ return nullptr;
+ }
+
+ QString errorString() const override
+ {
+ return m_errorString;
+ }
+
+public slots:
+ void doResponse(const QString &key, QtWayland::ServerBuffer *buffer)
+ {
+ if (key != m_id)
+ return; //somebody else's texture
+
+ m_buffer = buffer;
+
+ if (m_extension)
+ disconnect(m_extension, &QWaylandTextureSharingExtension::bufferResult, this, &SharedTextureImageResponse::doResponse);
+
+ emit finished();
+ }
+
+private:
+ QString m_id;
+ QWaylandTextureSharingExtension *m_extension = nullptr;
+ mutable QString m_errorString;
+ QtWayland::ServerBuffer *m_buffer = nullptr;
+};
+
+QWaylandSharedTextureProvider::QWaylandSharedTextureProvider()
+{
+}
+
+QWaylandSharedTextureProvider::~QWaylandSharedTextureProvider()
+{
+}
+
+QQuickImageResponse *QWaylandSharedTextureProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
+{
+ Q_UNUSED(requestedSize);
+
+// qDebug() << "Provider: got request for" << id;
+
+ auto *extension = QWaylandTextureSharingExtension::self();
+ auto *response = new SharedTextureImageResponse(extension, id);
+ if (!extension)
+ m_pendingResponses << response;
+
+ return response;
+}
+
+void QWaylandSharedTextureProvider::setExtensionReady(QWaylandTextureSharingExtension *extension)
+{
+ for (auto *response : qAsConst(m_pendingResponses))
+ response->doRequest(extension);
+ m_pendingResponses.clear();
+ m_pendingResponses.squeeze();
+}
+
+QWaylandTextureSharingExtension *QWaylandTextureSharingExtension::s_self = nullptr; // theoretical race conditions, but OK as long as we don't delete it while we are running
+
+QWaylandTextureSharingExtension::QWaylandTextureSharingExtension()
+{
+ s_self = this;
+}
+
+QWaylandTextureSharingExtension::QWaylandTextureSharingExtension(QWaylandCompositor *compositor)
+ :QWaylandCompositorExtensionTemplate(compositor)
+{
+ s_self = this;
+}
+
+QWaylandTextureSharingExtension::~QWaylandTextureSharingExtension()
+{
+ //qDebug() << Q_FUNC_INFO;
+ //dumpBufferInfo();
+
+ for (auto b : m_server_buffers)
+ delete b.buffer;
+
+ if (s_self == this)
+ s_self = nullptr;
+}
+
+void QWaylandTextureSharingExtension::setImageSearchPath(const QString &path)
+{
+ m_image_dirs = path.split(QLatin1Char(';'));
+
+ for (auto it = m_image_dirs.begin(); it != m_image_dirs.end(); ++it)
+ if (!(*it).endsWith(QLatin1Char('/')))
+ (*it) += QLatin1Char('/');
+}
+
+void QWaylandTextureSharingExtension::initialize()
+{
+ QWaylandCompositorExtensionTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ init(compositor->display(), 1);
+
+ QString image_search_path = qEnvironmentVariable("QT_WAYLAND_SHAREDTEXTURE_SEARCH_PATH");
+ if (!image_search_path.isEmpty())
+ setImageSearchPath(image_search_path);
+
+ if (m_image_dirs.isEmpty())
+ m_image_dirs << QLatin1Literal(":/") << QLatin1Literal("./");
+
+ auto suffixes = QTextureFileReader::supportedFileFormats();
+ suffixes.append(QImageReader::supportedImageFormats());
+ for (auto ext : qAsConst(suffixes))
+ m_image_suffixes << QLatin1Char('.') + QString::fromLatin1(ext);
+
+ //qDebug() << "m_image_suffixes" << m_image_suffixes << "m_image_dirs" << m_image_dirs;
+
+ auto *ctx = QQmlEngine::contextForObject(this);
+ if (ctx) {
+ QQmlEngine *engine = ctx->engine();
+ if (engine) {
+ auto *provider = static_cast<QWaylandSharedTextureProvider*>(engine->imageProvider(QLatin1Literal("wlshared")));
+ if (provider)
+ provider->setExtensionReady(this);
+ }
+ }
+}
+
+QString QWaylandTextureSharingExtension::getExistingFilePath(const QString &key) const
+{
+ // The default search path blocks absolute pathnames, but this does not prevent relative
+ // paths containing '../'. We handle that here, at the price of also blocking directory
+ // names ending with two or more dots.
+
+ if (key.contains(QLatin1Literal("../")))
+ return QString();
+
+ for (auto dir : m_image_dirs) {
+ QString path = dir + key;
+ if (QFileInfo::exists(path))
+ return path;
+ }
+
+ for (auto dir : m_image_dirs) {
+ for (auto ext : m_image_suffixes) {
+ QString fp = dir + key + ext;
+ //qDebug() << "trying" << fp;
+ if (QFileInfo::exists(fp))
+ return fp;
+ }
+ }
+ return QString();
+}
+
+QtWayland::ServerBuffer *QWaylandTextureSharingExtension::getBuffer(const QString &key)
+{
+ if (!initServerBufferIntegration())
+ return nullptr;
+
+//qDebug() << "getBuffer" << key;
+
+ QtWayland::ServerBuffer *buffer = nullptr;
+
+ if ((buffer = m_server_buffers.value(key).buffer))
+ return buffer;
+
+ QByteArray pixelData;
+ QSize size;
+ uint glInternalFormat = GL_NONE;
+
+ if (customPixelData(key, &pixelData, &size, &glInternalFormat)) {
+ if (!pixelData.isEmpty()) {
+ buffer = m_server_buffer_integration->createServerBufferFromData(pixelData, size, glInternalFormat);
+ if (!buffer)
+ qWarning() << "QWaylandTextureSharingExtension: could not create buffer from custom data for key:" << key;
+ }
+ } else {
+ QString pathName = getExistingFilePath(key);
+ //qDebug() << "pathName" << pathName;
+ if (pathName.isEmpty())
+ return nullptr;
+
+ buffer = getCompressedBuffer(pathName);
+ //qDebug() << "getCompressedBuffer" << buffer;
+
+ if (!buffer) {
+ QImage img(pathName);
+ if (!img.isNull()) {
+ img = img.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ buffer = m_server_buffer_integration->createServerBufferFromImage(img, QtWayland::ServerBuffer::RGBA32);
+ }
+ //qDebug() << "createServerBufferFromImage" << buffer;
+ }
+ }
+ if (buffer)
+ m_server_buffers.insert(key, BufferInfo(buffer));
+
+ //qDebug() << ">>>>" << key << buffer;
+
+ return buffer;
+}
+
+// Compositor requesting image for its own UI
+void QWaylandTextureSharingExtension::requestBuffer(const QString &key)
+{
+ //qDebug() << "requestBuffer" << key;
+
+ if (thread() != QThread::currentThread())
+ qWarning("QWaylandTextureSharingExtension::requestBuffer() called from outside main thread: possible race condition");
+
+ auto *buffer = getBuffer(key);
+
+ if (buffer)
+ m_server_buffers[key].usedLocally = true;
+
+ //dumpBufferInfo();
+
+ emit bufferResult(key, buffer);
+}
+
+void QWaylandTextureSharingExtension::zqt_texture_sharing_v1_request_image(Resource *resource, const QString &key)
+{
+ //qDebug() << "texture_sharing_request_image" << key;
+ auto *buffer = getBuffer(key);
+ if (buffer) {
+ struct ::wl_client *client = resource->client();
+ struct ::wl_resource *buffer_resource = buffer->resourceForClient(client);
+ //qDebug() << " server_buffer resource" << buffer_resource;
+ if (buffer_resource)
+ send_provide_buffer(resource->handle, buffer_resource, key);
+ else
+ qWarning() << "QWaylandTextureSharingExtension: no buffer resource for client";
+ } else {
+ send_image_failed(resource->handle, key, QString());
+ }
+ //dumpBufferInfo();
+}
+
+void QWaylandTextureSharingExtension::zqt_texture_sharing_v1_abandon_image(Resource *resource, const QString &key)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(key);
+// qDebug() << Q_FUNC_INFO << resource << key;
+ QTimer::singleShot(100, this, &QWaylandTextureSharingExtension::cleanupBuffers);
+}
+
+// A client has disconnected
+void QWaylandTextureSharingExtension::zqt_texture_sharing_v1_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource);
+// qDebug() << "texture_sharing_destroy_resource" << resource->handle << resource->handle->object.id << "client" << resource->client();
+// dumpBufferInfo();
+ QTimer::singleShot(1000, this, &QWaylandTextureSharingExtension::cleanupBuffers);
+}
+
+bool QWaylandTextureSharingExtension::initServerBufferIntegration()
+{
+ if (!m_server_buffer_integration) {
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+
+ m_server_buffer_integration = QWaylandCompositorPrivate::get(compositor)->serverBufferIntegration();
+ if (!m_server_buffer_integration) {
+ qWarning("QWaylandTextureSharingExtension initialization failed: No Server Buffer Integration");
+ if (qEnvironmentVariableIsEmpty("QT_WAYLAND_SERVER_BUFFER_INTEGRATION"))
+ qWarning("Set the environment variable 'QT_WAYLAND_SERVER_BUFFER_INTEGRATION' to specify.");
+ return false;
+ }
+ }
+ return true;
+}
+
+QtWayland::ServerBuffer *QWaylandTextureSharingExtension::getCompressedBuffer(const QString &pathName)
+{
+ QFile f(pathName);
+ if (!f.open(QIODevice::ReadOnly))
+ return nullptr;
+
+ QTextureFileReader r(&f, pathName);
+
+ if (!r.canRead())
+ return nullptr;
+
+ QTextureFileData td(r.read());
+
+ //qDebug() << "QWaylandTextureSharingExtension: reading compressed texture data" << td;
+
+ if (!td.isValid()) {
+ qWarning() << "VulkanServerBufferIntegration:" << pathName << "not valid compressed texture";
+ return nullptr;
+ }
+
+ QByteArray pixelData = QByteArray::fromRawData(td.data().constData() + td.dataOffset(), td.dataLength());
+
+ return m_server_buffer_integration->createServerBufferFromData(pixelData, td.size(), td.glInternalFormat());
+}
+
+void QWaylandTextureSharingExtension::cleanupBuffers()
+{
+ for (auto it = m_server_buffers.begin(); it != m_server_buffers.end(); ) {
+ auto *buffer = it.value().buffer;
+ if (!it.value().usedLocally && !buffer->bufferInUse()) {
+ //qDebug() << "deleting buffer for" << it.key();
+ it = m_server_buffers.erase(it);
+ delete buffer;
+ } else {
+ ++it;
+ }
+ }
+ //dumpBufferInfo();
+}
+
+void QWaylandTextureSharingExtension::dumpBufferInfo()
+{
+ qDebug() << "shared buffers:" << m_server_buffers.count();
+ for (auto it = m_server_buffers.cbegin(); it != m_server_buffers.cend(); ++it)
+ qDebug() << " " << it.key() << ":" << it.value().buffer << "in use" << it.value().buffer->bufferInUse() << "usedLocally" << it.value().usedLocally ;
+}
+
+QT_END_NAMESPACE
+
+#include "qwltexturesharingextension.moc"
diff --git a/src/compositor/extensions/qwltexturesharingextension_p.h b/src/compositor/extensions/qwltexturesharingextension_p.h
new file mode 100644
index 000000000..8f442a200
--- /dev/null
+++ b/src/compositor/extensions/qwltexturesharingextension_p.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 QWLTEXTURESHARINGEXTENSION_P_H
+#define QWLTEXTURESHARINGEXTENSION_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 "wayland-util.h"
+
+#include <QtCore/QMap>
+#include <QtCore/QHash>
+
+#include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate>
+#include <QtWaylandCompositor/QWaylandQuickExtension>
+#include <QtWaylandCompositor/QWaylandCompositor>
+
+#include <QQuickImageProvider>
+
+#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
+#include <QtWaylandCompositor/private/qwlserverbufferintegration_p.h>
+
+#include <QtWaylandCompositor/private/qwayland-server-qt-texture-sharing-unstable-v1.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWayland
+{
+ class ServerBufferIntegration;
+}
+
+class QWaylandTextureSharingExtension;
+class SharedTextureImageResponse;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSharedTextureProvider : public QQuickAsyncImageProvider
+{
+public:
+ QWaylandSharedTextureProvider();
+ ~QWaylandSharedTextureProvider() override;
+
+ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
+ void setExtensionReady(QWaylandTextureSharingExtension *extension);
+
+private:
+ QVector<SharedTextureImageResponse*> m_pendingResponses;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandTextureSharingExtension
+ : public QWaylandCompositorExtensionTemplate<QWaylandTextureSharingExtension>
+ , public QtWaylandServer::zqt_texture_sharing_v1
+{
+ Q_OBJECT
+ Q_PROPERTY(QString imageSearchPath WRITE setImageSearchPath)
+public:
+ QWaylandTextureSharingExtension();
+ QWaylandTextureSharingExtension(QWaylandCompositor *compositor);
+ ~QWaylandTextureSharingExtension() override;
+
+ void initialize() override;
+
+ void setImageSearchPath(const QString &path);
+
+ static QWaylandTextureSharingExtension *self() { return s_self; }
+
+public slots:
+ void requestBuffer(const QString &key);
+
+signals:
+ void bufferResult(const QString &key, QtWayland::ServerBuffer *buffer);
+
+protected slots:
+ void cleanupBuffers();
+
+protected:
+ void zqt_texture_sharing_v1_request_image(Resource *resource, const QString &key) override;
+ void zqt_texture_sharing_v1_abandon_image(Resource *resource, const QString &key) override;
+ void zqt_texture_sharing_v1_destroy_resource(Resource *resource) override;
+
+ virtual bool customPixelData(const QString &key, QByteArray *data, QSize *size, uint *glInternalFormat)
+ {
+ Q_UNUSED(key);
+ Q_UNUSED(data);
+ Q_UNUSED(size);
+ Q_UNUSED(glInternalFormat);
+ return false;
+ }
+
+private:
+ QtWayland::ServerBuffer *getBuffer(const QString &key);
+ bool initServerBufferIntegration();
+ QtWayland::ServerBuffer *getCompressedBuffer(const QString &key);
+ QString getExistingFilePath(const QString &key) const;
+ void dumpBufferInfo();
+
+ struct BufferInfo
+ {
+ BufferInfo(QtWayland::ServerBuffer *b = nullptr) : buffer(b) {}
+ QtWayland::ServerBuffer *buffer = nullptr;
+ bool usedLocally = false;
+ };
+
+ QStringList m_image_dirs;
+ QStringList m_image_suffixes;
+ QHash<QString, BufferInfo> m_server_buffers;
+ QtWayland::ServerBufferIntegration *m_server_buffer_integration = nullptr;
+
+ static QWaylandTextureSharingExtension *s_self;
+};
+
+Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandTextureSharingExtension)
+
+QT_END_NAMESPACE
+
+#endif // QWLTEXTURESHARINGEXTENSION_P_H
diff --git a/src/extensions/qt-texture-sharing-unstable-v1.xml b/src/extensions/qt-texture-sharing-unstable-v1.xml
new file mode 100644
index 000000000..262ae487c
--- /dev/null
+++ b/src/extensions/qt-texture-sharing-unstable-v1.xml
@@ -0,0 +1,57 @@
+<protocol name="qt_texture_sharing_unstable_v1">
+
+ <copyright>
+ Copyright (C) 2019 The Qt Company Ltd.
+ Contact: http://www.qt.io/licensing/
+
+ This file is part of the plugins of the Qt Toolkit.
+
+ $QT_BEGIN_LICENSE:BSD$
+ 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$
+ </copyright>
+
+ <interface name="zqt_texture_sharing_v1" version="1">
+ <request name="request_image">
+ <arg name="key" type="string"/>
+ </request>
+ <request name="abandon_image">
+ <arg name="key" type="string"/>
+ </request>
+ <event name="image_failed">
+ <arg name="key" type="string"/>
+ <arg name="error_message" type="string"/>
+ </event>
+ <event name="provide_buffer">
+ <arg name="buffer" type="object" interface="qt_server_buffer"/>
+ <arg name="key" type="string"/>
+ </event>
+ </interface>
+</protocol>
diff --git a/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp b/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp
index bc6fe7f05..2b39c3ffa 100644
--- a/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp
+++ b/src/hardwareintegration/compositor/vulkan-server/vulkanwrapper.cpp
@@ -56,6 +56,8 @@
#include <QDebug>
+QT_BEGIN_NAMESPACE
+
static constexpr bool extraDebug = false;
#define DECL_VK_FUNCTION(name) \
@@ -727,3 +729,5 @@ void VulkanWrapper::freeTextureImage(VulkanImageWrapper *imageWrapper)
{
d_ptr->freeTextureImage(imageWrapper);
}
+
+QT_END_NAMESPACE
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index c57c95d20..c8394f0c1 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,3 +1,8 @@
TEMPLATE = subdirs
-qtHaveModule(quick): SUBDIRS += compositor
+qtHaveModule(quick): {
+ SUBDIRS += \
+ compositor \
+ texture-sharing \
+ texture-sharing-extension
+}
diff --git a/src/imports/texture-sharing-extension/plugin.cpp b/src/imports/texture-sharing-extension/plugin.cpp
new file mode 100644
index 000000000..42dcd8e2d
--- /dev/null
+++ b/src/imports/texture-sharing-extension/plugin.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** 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 <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqmlengine.h>
+
+#include "QtWaylandCompositor/private/qwltexturesharingextension_p.h"
+
+/*!
+ \qmlmodule QtWayland.Compositor.TextureSharingExtension 1
+ \title Qt Wayland Shared Texture Provider
+ \ingroup qmlmodules
+ \brief Adds a mechanism to share GPU memory
+
+ \section2 Summary
+
+ This module lets the compositor export graphical resources that can be used by clients,
+ without allocating any graphics memory in the client.
+
+ \section2 Usage
+
+ This module is imported like this:
+
+ \code
+ import QtWayland.Compositor.TextureSharingExtension 1.0
+ \endcode
+
+ To use this module in a compositor, instantiate the extension object as a child of the compositor object, like this:
+
+
+ \code
+ WaylandCompositor {
+ //...
+ TextureSharingExtension {
+ }
+ }
+ \endcode
+
+ The sharing functionality is provided through a QQuickImageProvider. Use
+ the "image:" scheme for the URL source of the image, followed by the
+ identifier \e wlshared, followed by the image file path. For example:
+
+ \code
+ Image { source: "image://wlshared/wallpapers/mybackground.jpg" }
+ \endcode
+
+*/
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandTextureSharingExtensionPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+public:
+ QWaylandTextureSharingExtensionPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) {}
+
+ void registerTypes(const char *uri) override
+ {
+ Q_ASSERT(uri == QStringLiteral("QtWayland.Compositor.TextureSharingExtension"));
+ qmlRegisterType<QWaylandTextureSharingExtensionQuickExtension>("QtWayland.Compositor.TextureSharingExtension", 1, 0, "TextureSharingExtension");
+ }
+
+ void initializeEngine(QQmlEngine *engine, const char *uri) override
+ {
+ Q_UNUSED(uri);
+ engine->addImageProvider("wlshared", new QWaylandSharedTextureProvider);
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/texture-sharing-extension/qmldir b/src/imports/texture-sharing-extension/qmldir
new file mode 100644
index 000000000..182e5c0ee
--- /dev/null
+++ b/src/imports/texture-sharing-extension/qmldir
@@ -0,0 +1,3 @@
+module QtWayland.Compositor.TextureSharingExtension
+plugin qwaylandtexturesharingextension
+classname QWaylandTextureSharingExtensionPlugin
diff --git a/src/imports/texture-sharing-extension/texture-sharing-extension.pro b/src/imports/texture-sharing-extension/texture-sharing-extension.pro
new file mode 100644
index 000000000..68a8cf757
--- /dev/null
+++ b/src/imports/texture-sharing-extension/texture-sharing-extension.pro
@@ -0,0 +1,11 @@
+CXX_MODULE = qml
+TARGET = qwaylandtexturesharingextension
+TARGETPATH = QtWayland/Compositor/TextureSharingExtension
+IMPORT_VERSION = 1.$$QT_MINOR_VERSION
+
+SOURCES += \
+ plugin.cpp
+
+QT += quick-private qml gui-private core-private waylandcompositor waylandcompositor-private
+
+load(qml_plugin)
diff --git a/src/imports/texture-sharing/plugin.cpp b/src/imports/texture-sharing/plugin.cpp
new file mode 100644
index 000000000..9cf6bbca1
--- /dev/null
+++ b/src/imports/texture-sharing/plugin.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandClient 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 <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqmlengine.h>
+
+#include "sharedtextureprovider.h"
+
+/*!
+ \qmlmodule QtWayland.Client.TextureSharing 1
+ \title Qt Wayland Shared Texture Provider
+ \ingroup qmlmodules
+ \brief Adds an image provider which utilizes shared GPU memory
+
+ \section2 Summary
+
+ This module allows Qt Wayland clients to use graphical resources exported
+ by the compositor, without allocating any graphics memory in the client.
+ \section2 Usage
+
+ To use this module, import it like this:
+ \code
+ import QtWayland.Client.TextureSharing 1.0
+ \endcode
+
+ The sharing functionality is provided through a QQuickImageProvider. Use
+ the "image:" scheme for the URL source of the image, followed by the
+ identifier \e wlshared, followed by the image file path. For example:
+
+ \code
+ Image { source: "image://wlshared/wallpapers/mybackground.jpg" }
+ \endcode
+
+ The shared texture module does not provide any directly usable QML types.
+*/
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandTextureSharingPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+public:
+ QWaylandTextureSharingPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) {}
+
+ void registerTypes(const char *uri) override
+ {
+ Q_ASSERT(uri == QStringLiteral("QtWayland.Client.TextureSharing"));
+ qmlRegisterModule(uri, 1, 0);
+ }
+
+ void initializeEngine(QQmlEngine *engine, const char *uri) override
+ {
+ Q_UNUSED(uri);
+ engine->addImageProvider("wlshared", new SharedTextureProvider);
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/texture-sharing/qmldir b/src/imports/texture-sharing/qmldir
new file mode 100644
index 000000000..cf3b74c48
--- /dev/null
+++ b/src/imports/texture-sharing/qmldir
@@ -0,0 +1,3 @@
+module QtWayland.Client.TextureSharing
+plugin qwaylandtexturesharing
+classname QWaylandTextureSharingPlugin
diff --git a/src/imports/texture-sharing/sharedtextureprovider.cpp b/src/imports/texture-sharing/sharedtextureprovider.cpp
new file mode 100644
index 000000000..707e94ae6
--- /dev/null
+++ b/src/imports/texture-sharing/sharedtextureprovider.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** 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 "sharedtextureprovider.h"
+
+#include <QFile>
+#include <QDebug>
+#include <qopenglfunctions.h>
+#include <QQuickWindow>
+
+#include <QtWaylandClient/private/qwaylandintegration_p.h>
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QtGui/QWindow>
+#include <QOpenGLTexture>
+#include <QImageReader>
+
+#include <QTimer>
+
+#include "texturesharingextension.h"
+
+QT_BEGIN_NAMESPACE
+
+SharedTexture::SharedTexture(QtWaylandClient::QWaylandServerBuffer *buffer)
+ : m_buffer(buffer), m_tex(nullptr)
+{
+}
+
+int SharedTexture::textureId() const
+{
+ updateGLTexture();
+ return m_tex ? m_tex->textureId() : 0;
+}
+
+QSize SharedTexture::textureSize() const
+{
+ updateGLTexture();
+ return m_tex ? QSize(m_tex->width(), m_tex->height()) : QSize();
+}
+
+bool SharedTexture::hasAlphaChannel() const
+{
+ return true;
+}
+
+bool SharedTexture::hasMipmaps() const
+{
+ updateGLTexture();
+ return m_tex ? (m_tex->mipLevels() > 1) : false;
+}
+
+void SharedTexture::bind()
+{
+ updateGLTexture();
+ if (m_tex)
+ m_tex->bind();
+}
+
+inline void SharedTexture::updateGLTexture() const
+{
+ if (!m_tex && m_buffer)
+ m_tex = m_buffer->toOpenGlTexture();
+}
+
+class SharedTextureFactory : public QQuickTextureFactory
+{
+public:
+ SharedTextureFactory(const QtWaylandClient::QWaylandServerBuffer *buffer, const QString &id, SharedTextureRegistry *registry)
+ : m_buffer(buffer), m_id(id), m_registry(registry)
+ {
+ }
+
+ ~SharedTextureFactory() override
+ {
+ //qDebug() << "====> DESTRUCTOR SharedTextureFactory" << this;
+ if (m_registry)
+ m_registry->abandonBuffer(m_id);
+ delete m_buffer; // TODO: make sure we are not keeping references to this elsewhere
+ //qDebug() << "buffer deleted";
+ }
+
+ QSize textureSize() const override
+ {
+ return m_buffer ? m_buffer->size() : QSize();
+ }
+
+ int textureByteCount() const override
+ {
+ return m_buffer ? (m_buffer->size().width() * m_buffer->size().height() * 4) : 0;
+ }
+
+ QSGTexture *createTexture(QQuickWindow *) const override
+ {
+ return new SharedTexture(const_cast<QtWaylandClient::QWaylandServerBuffer *>(m_buffer));
+ }
+
+private:
+ const QtWaylandClient::QWaylandServerBuffer *m_buffer = nullptr;
+ QString m_id;
+ QPointer<SharedTextureRegistry> m_registry;
+};
+
+
+SharedTextureRegistry::SharedTextureRegistry()
+ : m_extension(new TextureSharingExtension)
+{
+ connect(m_extension, &TextureSharingExtension::bufferReceived, this, &SharedTextureRegistry::receiveBuffer);
+ connect(m_extension, &TextureSharingExtension::activeChanged, this, &SharedTextureRegistry::handleExtensionActive);
+}
+
+SharedTextureRegistry::~SharedTextureRegistry()
+{
+ delete m_extension;
+}
+
+const QtWaylandClient::QWaylandServerBuffer *SharedTextureRegistry::bufferForId(const QString &id) const
+{
+ return m_buffers.value(id);
+}
+
+void SharedTextureRegistry::requestBuffer(const QString &id)
+{
+ if (!m_extension->isActive()) {
+ //qDebug() << "Extension not active, adding" << id << "to queue";
+ m_pendingBuffers << id;
+ return;
+ }
+ m_extension->requestImage(id);
+}
+
+void SharedTextureRegistry::abandonBuffer(const QString &id)
+{
+ m_buffers.remove(id);
+ m_extension->abandonImage(id);
+}
+
+
+void SharedTextureRegistry::handleExtensionActive()
+{
+ //qDebug() << "handleExtensionActive, queue:" << m_pendingBuffers;
+ if (m_extension->isActive())
+ while (!m_pendingBuffers.isEmpty())
+ requestBuffer(m_pendingBuffers.takeFirst());
+}
+
+bool SharedTextureRegistry::preinitialize()
+{
+ auto *serverBufferIntegration = QGuiApplicationPrivate::platformIntegration()->nativeInterface()->nativeResourceForIntegration("server_buffer_integration");
+
+ if (!serverBufferIntegration) {
+ qWarning() << "Wayland Server Buffer Integration not available.";
+ return false;
+ }
+
+ return true;
+}
+
+void SharedTextureRegistry::receiveBuffer(QtWaylandClient::QWaylandServerBuffer *buffer, const QString& id)
+{
+ //qDebug() << "ReceiveBuffer for id" << id;
+ if (buffer)
+ m_buffers.insert(id, buffer);
+ emit replyReceived(id);
+}
+
+class SharedTextureImageResponse : public QQuickImageResponse
+{
+ Q_OBJECT
+public:
+ SharedTextureImageResponse(SharedTextureRegistry *registry, const QString &id)
+ : m_id(id), m_registry(registry)
+ {
+ if (!m_registry || m_registry->bufferForId(id)) {
+ // Shortcut: no server roundtrip needed, just let the event loop call the slot
+ QMetaObject::invokeMethod(this, "doResponse", Qt::QueuedConnection, Q_ARG(QString, id));
+
+ } else {
+ // TBD: timeout?
+ connect(registry, &SharedTextureRegistry::replyReceived, this, &SharedTextureImageResponse::doResponse);
+ registry->requestBuffer(id);
+ }
+ }
+
+ QQuickTextureFactory *textureFactory() const override
+ {
+ if (m_registry) {
+ const QtWaylandClient::QWaylandServerBuffer *buffer = m_registry->bufferForId(m_id);
+ if (buffer) {
+ //qDebug() << "Creating shared buffer texture for" << m_id;
+ return new SharedTextureFactory(buffer, m_id, m_registry);
+ }
+ //qDebug() << "Shared buffer NOT found for" << m_id;
+ }
+
+ // No shared buffer, do fallback
+ QString fbPath = fallbackPath();
+ if (fbPath.isEmpty()) {
+ m_errorString = QStringLiteral("Shared buffer not found, and no fallback path set.");
+ return nullptr;
+ }
+
+ QImageReader reader(fbPath + m_id);
+ QImage img = reader.read();
+ if (img.isNull()) {
+ qWarning() << "Could not load local image from id/path" << reader.fileName();
+ m_errorString = QStringLiteral("Shared buffer not found, and fallback local file loading failed: ") + reader.errorString();
+ return nullptr;
+ }
+ return QQuickTextureFactory::textureFactoryForImage(img);
+ }
+
+ QString errorString() const override
+ {
+ return m_errorString;
+ }
+
+ static QString fallbackPath()
+ {
+ static QString fbPath;
+ static bool isInit = false;
+ if (!isInit) {
+ isInit = true;
+ QByteArray envVal = qgetenv("QT_SHAREDTEXTURE_FALLBACK_DIR");
+ if (!envVal.isEmpty()) {
+ fbPath = QString::fromLocal8Bit(envVal);
+ if (!fbPath.endsWith(QLatin1Char('/')))
+ fbPath.append(QLatin1Char('/'));
+ }
+ }
+ return fbPath;
+ }
+
+
+public slots:
+ void doResponse(const QString &key) {
+ if (key != m_id)
+ return; // not our buffer
+
+ // No need to be called again
+ if (m_registry)
+ disconnect(m_registry, &SharedTextureRegistry::replyReceived, this, &SharedTextureImageResponse::doResponse);
+
+ emit finished();
+ }
+
+private:
+ QString m_id;
+ SharedTextureRegistry *m_registry = nullptr;
+ mutable QString m_errorString;
+};
+
+
+SharedTextureProvider::SharedTextureProvider()
+{
+ m_sharingAvailable = SharedTextureRegistry::preinitialize();
+ if (!m_sharingAvailable) {
+ if (SharedTextureImageResponse::fallbackPath().isEmpty())
+ qWarning() << "Shared buffer images not available, and no fallback directory set.";
+ else
+ qWarning() << "Shared buffer images not available, will fallback to local image files from" << SharedTextureImageResponse::fallbackPath();
+ }
+}
+
+SharedTextureProvider::~SharedTextureProvider()
+{
+ delete m_registry;
+}
+
+QQuickImageResponse *SharedTextureProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
+{
+ Q_UNUSED(requestedSize);
+
+ //qDebug() << "Provider: got request for" << id;
+
+ if (m_sharingAvailable && !m_registry)
+ m_registry = new SharedTextureRegistry;
+
+ return new SharedTextureImageResponse(m_registry, id);
+}
+
+QT_END_NAMESPACE
+
+#include "sharedtextureprovider.moc"
diff --git a/src/imports/texture-sharing/sharedtextureprovider.h b/src/imports/texture-sharing/sharedtextureprovider.h
new file mode 100644
index 000000000..f25c7de9c
--- /dev/null
+++ b/src/imports/texture-sharing/sharedtextureprovider.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** 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 SHAREDTEXTUREPROVIDER_H
+#define SHAREDTEXTUREPROVIDER_H
+
+#include <QOpenGLFunctions>
+#include <QQuickImageProvider>
+#include <QtQuick/QSGTexture>
+#include <QScopedPointer>
+#include <QHash>
+
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class TextureSharingExtension;
+
+class SharedTextureRegistry : public QObject
+{
+ Q_OBJECT
+public:
+ SharedTextureRegistry();
+ ~SharedTextureRegistry() override;
+
+ const QtWaylandClient::QWaylandServerBuffer *bufferForId(const QString &id) const;
+ void requestBuffer(const QString &id);
+ void abandonBuffer(const QString &id);
+
+ static bool preinitialize();
+
+public slots:
+ void receiveBuffer(QtWaylandClient::QWaylandServerBuffer *buffer, const QString &id);
+
+signals:
+ void replyReceived(const QString &id);
+
+private slots:
+ void handleExtensionActive();
+
+private:
+ TextureSharingExtension *m_extension = nullptr;
+ QHash<QString, QtWaylandClient::QWaylandServerBuffer *> m_buffers;
+ QStringList m_pendingBuffers;
+};
+
+class SharedTextureProvider : public QQuickAsyncImageProvider
+{
+public:
+ SharedTextureProvider();
+ ~SharedTextureProvider() override;
+
+ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
+
+private:
+ SharedTextureRegistry *m_registry = nullptr;
+ bool m_sharingAvailable = false;
+};
+
+class SharedTexture : public QSGTexture
+{
+ Q_OBJECT
+public:
+ SharedTexture(QtWaylandClient::QWaylandServerBuffer *buffer);
+
+ int textureId() const override;
+ QSize textureSize() const override;
+ bool hasAlphaChannel() const override;
+ bool hasMipmaps() const override;
+
+ void bind() override;
+
+private:
+ void updateGLTexture() const;
+ QtWaylandClient::QWaylandServerBuffer *m_buffer = nullptr;
+ mutable QOpenGLTexture *m_tex = nullptr;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // SHAREDTEXTUREPROVIDER_H
diff --git a/src/imports/texture-sharing/texture-sharing.pro b/src/imports/texture-sharing/texture-sharing.pro
new file mode 100644
index 000000000..bec769ecb
--- /dev/null
+++ b/src/imports/texture-sharing/texture-sharing.pro
@@ -0,0 +1,21 @@
+CXX_MODULE = qml
+TARGET = qwaylandtexturesharing
+TARGETPATH = QtWayland/Client/TextureSharing
+IMPORT_VERSION = 1.$$QT_MINOR_VERSION
+
+HEADERS += \
+ sharedtextureprovider.h \
+ texturesharingextension.h
+
+SOURCES += \
+ plugin.cpp \
+ sharedtextureprovider.cpp \
+ texturesharingextension.cpp
+
+QT += quick-private qml gui-private core-private waylandclient waylandclient-private
+CONFIG += wayland-scanner
+
+WAYLANDCLIENTSOURCES += ../../extensions/qt-texture-sharing-unstable-v1.xml
+
+
+load(qml_plugin)
diff --git a/src/imports/texture-sharing/texturesharingextension.cpp b/src/imports/texture-sharing/texturesharingextension.cpp
new file mode 100644
index 000000000..31106d694
--- /dev/null
+++ b/src/imports/texture-sharing/texturesharingextension.cpp
@@ -0,0 +1,86 @@
+
+/****************************************************************************
+**
+** 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 "texturesharingextension.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/private/qwaylandintegration_p.h>
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/QWindow>
+#include <QtGui/QPlatformSurfaceEvent>
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+TextureSharingExtension::TextureSharingExtension()
+ : QWaylandClientExtensionTemplate(/* Supported protocol version */ 1 )
+{
+ auto *wayland_integration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ m_server_buffer_integration = wayland_integration->serverBufferIntegration();
+ if (!m_server_buffer_integration) {
+ qCritical() << "This application requires a working serverBufferIntegration";
+ QGuiApplication::quit();
+ }
+}
+
+void TextureSharingExtension::zqt_texture_sharing_v1_provide_buffer(struct ::qt_server_buffer *buffer, const QString &key)
+{
+ QtWaylandClient::QWaylandServerBuffer *serverBuffer = m_server_buffer_integration->serverBuffer(buffer);
+ emit bufferReceived(serverBuffer, key);
+}
+
+void TextureSharingExtension::zqt_texture_sharing_v1_image_failed(const QString &key, const QString &message)
+{
+ qWarning() << "TextureSharingExtension" << key << "not found" << message;
+ emit bufferReceived(nullptr, key);
+}
+void TextureSharingExtension::requestImage(const QString &key)
+{
+ request_image(key);
+}
+
+void TextureSharingExtension::abandonImage(const QString &key)
+{
+ abandon_image(key);
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/texture-sharing/texturesharingextension.h b/src/imports/texture-sharing/texturesharingextension.h
new file mode 100644
index 000000000..7b864fbc8
--- /dev/null
+++ b/src/imports/texture-sharing/texturesharingextension.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 TEXTURESHARINGEXTENSION_H
+#define TEXTURESHARINGEXTENSION_H
+
+#include <qpa/qwindowsysteminterface.h>
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtWaylandClient/qwaylandclientextension.h>
+#include "qwayland-qt-texture-sharing-unstable-v1.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+ class QWaylandServerBuffer;
+ class QWaylandServerBufferIntegration;
+};
+
+class TextureSharingExtension : public QWaylandClientExtensionTemplate<TextureSharingExtension>
+ , public QtWayland::zqt_texture_sharing_v1
+{
+ Q_OBJECT
+public:
+ TextureSharingExtension();
+
+public slots:
+ void requestImage(const QString &key);
+ void abandonImage(const QString &key);
+
+signals:
+ void bufferReceived(QtWaylandClient::QWaylandServerBuffer *buffer, const QString &key);
+
+private:
+ void zqt_texture_sharing_v1_provide_buffer(struct ::qt_server_buffer *buffer, const QString &key) override;
+ void zqt_texture_sharing_v1_image_failed(const QString &key, const QString &message) override;
+ QtWaylandClient::QWaylandServerBufferIntegration *m_server_buffer_integration = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // TEXTURESHARINGEXTENSION_H
diff --git a/src/src.pro b/src/src.pro
index 4ecbc71b9..db7d72753 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -20,7 +20,7 @@ qtConfig(wayland-client) {
SUBDIRS += sub_compositor
sub_imports.subdir = imports
- sub_imports.depends += sub-compositor
+ sub_imports.depends += sub-compositor sub-client
sub_imports.target = sub-imports
SUBDIRS += sub_imports