Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
sharedtextureprovider.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
6
7#include <QFile>
8#include <QDebug>
9#include <qopenglfunctions.h>
10#include <QQuickWindow>
11
12#include <QtWaylandClient/private/qwaylandintegration_p.h>
13#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
14#include <QtGui/QGuiApplication>
15#include <QtGui/private/qguiapplication_p.h>
16#include <QtQuick/private/qsgrhisupport_p.h>
17#include <QtGui/qpa/qplatformnativeinterface.h>
18#include <QtGui/QWindow>
19#include <QOpenGLTexture>
20#include <QImageReader>
21
22#include <QtCore/qpointer.h>
23#include <QTimer>
24
26
28
30{
31public:
33 : m_buffer(buffer), m_id(id), m_registry(registry)
34 {
35 }
36
38 {
39 //qDebug() << "====> DESTRUCTOR SharedTextureFactory" << this;
40 if (m_registry)
41 m_registry->abandonBuffer(m_id);
42 delete m_buffer; // TODO: make sure we are not keeping references to this elsewhere
43 //qDebug() << "buffer deleted";
44 }
45
46 QSize textureSize() const override
47 {
48 return m_buffer ? m_buffer->size() : QSize();
49 }
50
51 int textureByteCount() const override
52 {
53 return m_buffer ? (m_buffer->size().width() * m_buffer->size().height() * 4) : 0;
54 }
55
57 {
58 if (m_buffer != nullptr) {
59 QOpenGLTexture *texture = const_cast<QtWaylandClient::QWaylandServerBuffer *>(m_buffer)->toOpenGlTexture();
60 return QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(),
61 window,
62 m_buffer->size(),
63 QQuickWindow::TextureHasAlphaChannel);
64 }
65 return nullptr;
66 }
67
68private:
69 const QtWaylandClient::QWaylandServerBuffer *m_buffer = nullptr;
70 QString m_id;
71 QPointer<SharedTextureRegistry> m_registry;
72};
73
74
76 : m_extension(new TextureSharingExtension)
77{
79 connect(m_extension, &TextureSharingExtension::activeChanged, this, &SharedTextureRegistry::handleExtensionActive);
80}
81
83{
84 delete m_extension;
85}
86
88{
89 return m_buffers.value(id);
90}
91
93{
94 if (!m_extension->isActive()) {
95 //qDebug() << "Extension not active, adding" << id << "to queue";
96 m_pendingBuffers << id;
97 return;
98 }
99 m_extension->requestImage(id);
100}
101
103{
104 m_buffers.remove(id);
105 m_extension->abandonImage(id);
106}
107
108
109void SharedTextureRegistry::handleExtensionActive()
110{
111 //qDebug() << "handleExtensionActive, queue:" << m_pendingBuffers;
112 if (m_extension->isActive())
113 while (!m_pendingBuffers.isEmpty())
114 requestBuffer(m_pendingBuffers.takeFirst());
115}
116
118{
119 if (QSGRhiSupport::instance()->rhiBackend() != QRhi::OpenGLES2) {
120 qWarning() << "The shared-texture extension is only supported on OpenGL. Use QQuickWindow::setSceneGraphBackend() to override the default.";
121 return false;
122 }
123
124 auto *serverBufferIntegration = QGuiApplicationPrivate::platformIntegration()->nativeInterface()->nativeResourceForIntegration("server_buffer_integration");
125
126 if (!serverBufferIntegration) {
127 qWarning() << "Wayland Server Buffer Integration not available.";
128 return false;
129 }
130
131 return true;
132}
133
135{
136 //qDebug() << "ReceiveBuffer for id" << id;
137 if (buffer)
138 m_buffers.insert(id, buffer);
140}
141
143{
145public:
147 : m_id(id), m_registry(registry)
148 {
149 if (!m_registry || m_registry->bufferForId(id)) {
150 // Shortcut: no server roundtrip needed, just let the event loop call the slot
152
153 } else {
154 // TBD: timeout?
156 registry->requestBuffer(id);
157 }
158 }
159
161 {
162 if (m_registry) {
164 if (buffer) {
165 //qDebug() << "Creating shared buffer texture for" << m_id;
166 return new SharedTextureFactory(buffer, m_id, m_registry);
167 }
168 //qDebug() << "Shared buffer NOT found for" << m_id;
169 }
170
171 // No shared buffer, do fallback
172 QString fbPath = fallbackPath();
173 if (fbPath.isEmpty()) {
174 m_errorString = QStringLiteral("Shared buffer not found, and no fallback path set.");
175 return nullptr;
176 }
177
178 QImageReader reader(fbPath + m_id);
179 QImage img = reader.read();
180 if (img.isNull()) {
181 qWarning() << "Could not load local image from id/path" << reader.fileName();
182 m_errorString = QStringLiteral("Shared buffer not found, and fallback local file loading failed: ") + reader.errorString();
183 return nullptr;
184 }
186 }
187
188 QString errorString() const override
189 {
190 return m_errorString;
191 }
192
194 {
195 static QString fbPath;
196 static bool isInit = false;
197 if (!isInit) {
198 isInit = true;
199 QByteArray envVal = qgetenv("QT_SHAREDTEXTURE_FALLBACK_DIR");
200 if (!envVal.isEmpty()) {
201 fbPath = QString::fromLocal8Bit(envVal);
202 if (!fbPath.endsWith(QLatin1Char('/')))
203 fbPath.append(QLatin1Char('/'));
204 }
205 }
206 return fbPath;
207 }
208
209
210public Q_SLOTS:
211 void doResponse(const QString &key) {
212 if (key != m_id)
213 return; // not our buffer
214
215 // No need to be called again
216 if (m_registry)
218
219 emit finished();
220 }
221
222private:
223 QString m_id;
224 SharedTextureRegistry *m_registry = nullptr;
225 mutable QString m_errorString;
226};
227
228
230{
231 m_sharingAvailable = SharedTextureRegistry::preinitialize();
232 if (!m_sharingAvailable) {
234 qWarning() << "Shared buffer images not available, and no fallback directory set.";
235 else
236 qWarning() << "Shared buffer images not available, will fallback to local image files from" << SharedTextureImageResponse::fallbackPath();
237 }
238}
239
241{
242 delete m_registry;
243}
244
246{
247 Q_UNUSED(requestedSize);
248
249 //qDebug() << "Provider: got request for" << id;
250
251 if (m_sharingAvailable && !m_registry)
252 m_registry = new SharedTextureRegistry;
253
254 return new SharedTextureImageResponse(m_registry, id);
255}
256
258
259#include "moc_sharedtextureprovider_p.cpp"
260
261#include "sharedtextureprovider.moc"
\inmodule QtCore
Definition qbytearray.h:57
static QPlatformIntegration * platformIntegration()
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:958
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
The QImageReader class provides a format independent interface for reading images from files or other...
QString errorString() const
Returns a human readable description of the last error that occurred.
QString fileName() const
If the currently assigned device is a QFile, or if setFileName() has been called, this function retur...
QImage read()
Reads an image from the device.
\inmodule QtGui
Definition qimage.h:37
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtGui
The QQuickImageResponse class provides an interface for asynchronous image loading in QQuickAsyncImag...
void finished()
Signals that the job execution has finished (be it successfully, because an error happened or because...
The QQuickTextureFactory class provides an interface for loading custom textures from QML....
static QQuickTextureFactory * textureFactoryForImage(const QImage &image)
Returns a QQuickTextureFactory holding the given image.
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
@ OpenGLES2
Definition qrhi.h:1809
static QSGRhiSupport * instance()
\inmodule QtQuick
Definition qsgtexture.h:20
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
QSGTexture * createTexture(QQuickWindow *window) const override
This function is called on the scene graph rendering thread to create a QSGTexture instance from the ...
SharedTextureFactory(const QtWaylandClient::QWaylandServerBuffer *buffer, const QString &id, SharedTextureRegistry *registry)
QSize textureSize() const override
Returns the size of the texture.
int textureByteCount() const override
Returns the number of bytes of memory the texture consumes.
void doResponse(const QString &key, QtWayland::ServerBuffer *buffer)
void doResponse(const QString &key)
QString errorString() const override
Returns the error string for the job execution.
SharedTextureImageResponse(SharedTextureRegistry *registry, const QString &id)
QQuickTextureFactory * textureFactory() const override
Returns the texture factory for the job.
QQuickImageResponse * requestImageResponse(const QString &id, const QSize &requestedSize) override
Implement this method to return the job that will provide the texture with id.
const QtWaylandClient::QWaylandServerBuffer * bufferForId(const QString &id) const
void receiveBuffer(QtWaylandClient::QWaylandServerBuffer *buffer, const QString &id)
void abandonBuffer(const QString &id)
void requestBuffer(const QString &id)
void replyReceived(const QString &id)
void abandonImage(const QString &key)
void requestImage(const QString &key)
void bufferReceived(QtWaylandClient::QWaylandServerBuffer *buffer, const QString &key)
Combined button and popup list for selecting options.
@ QueuedConnection
#define qWarning
Definition qlogging.h:166
#define Q_ARG(Type, data)
Definition qobjectdefs.h:63
GLuint64 key
GLenum GLuint id
[7]
GLenum GLuint buffer
GLenum GLuint texture
GLint void * img
Definition qopenglext.h:233
#define QStringLiteral(str)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_OBJECT
#define Q_SLOTS
#define emit
#define Q_UNUSED(x)
myObject disconnect()
[26]
aWidget window() -> setWindowTitle("New Window Title")
[2]
\inmodule QtCore \reentrant
Definition qchar.h:18
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...