1 | // Copyright (C) 2017 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 | #include "shmserverbufferintegration.h" |
5 | #include <QtWaylandClient/private/qwaylanddisplay_p.h> |
6 | #include <QDebug> |
7 | #include <QtOpenGL/QOpenGLTexture> |
8 | #include <QtGui/QOpenGLContext> |
9 | #include <QtGui/QImage> |
10 | #include <QtCore/QSharedMemory> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | static QOpenGLTexture *createTextureFromShm(const QString &key, int w, int h, int bpl, int format) |
15 | { |
16 | QT_IGNORE_DEPRECATIONS(QSharedMemory shm(key);) |
17 | bool ok; |
18 | ok = shm.attach(mode: QSharedMemory::ReadOnly); |
19 | if (!ok) { |
20 | qWarning() << "Could not attach to" << key; |
21 | return nullptr; |
22 | } |
23 | ok = shm.lock(); |
24 | if (!ok) { |
25 | qWarning() << "Could not lock" << key << "for reading" ; |
26 | return nullptr; |
27 | } |
28 | |
29 | QImage::Format imageFormat; |
30 | switch (format) { |
31 | case QtWayland::qt_shm_emulation_server_buffer::format_RGBA32: |
32 | imageFormat = QImage::Format_RGBA8888; |
33 | break; |
34 | case QtWayland::qt_shm_emulation_server_buffer::format_A8: |
35 | imageFormat = QImage::Format_Alpha8; |
36 | break; |
37 | default: |
38 | qWarning() << "ShmServerBuffer: unknown format" << format; |
39 | imageFormat = QImage::Format_RGBA8888; |
40 | break; |
41 | } |
42 | |
43 | QImage image(static_cast<const uchar*>(shm.constData()), w, h, bpl, imageFormat); |
44 | |
45 | if (!QOpenGLContext::currentContext()) |
46 | qWarning(msg: "ShmServerBuffer: creating texture with no current context" ); |
47 | |
48 | auto *tex = new QOpenGLTexture(image, QOpenGLTexture::DontGenerateMipMaps); |
49 | shm.unlock(); |
50 | return tex; |
51 | } |
52 | |
53 | |
54 | namespace QtWaylandClient { |
55 | |
56 | ShmServerBuffer::ShmServerBuffer(const QString &key, const QSize& size, int bytesPerLine, QWaylandServerBuffer::Format format) |
57 | : m_key(key) |
58 | , m_bpl(bytesPerLine) |
59 | { |
60 | m_format = format; |
61 | m_size = size; |
62 | } |
63 | |
64 | ShmServerBuffer::~ShmServerBuffer() |
65 | { |
66 | } |
67 | |
68 | QOpenGLTexture *ShmServerBuffer::toOpenGlTexture() |
69 | { |
70 | if (!m_texture) |
71 | m_texture = createTextureFromShm(key: m_key, w: m_size.width(), h: m_size.height(), bpl: m_bpl, format: m_format); |
72 | |
73 | return m_texture; |
74 | } |
75 | |
76 | void ShmServerBufferIntegration::initialize(QWaylandDisplay *display) |
77 | { |
78 | m_display = display; |
79 | display->addRegistryListener(listener: &wlDisplayHandleGlobal, data: this); |
80 | } |
81 | |
82 | QWaylandServerBuffer *ShmServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer) |
83 | { |
84 | return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer)); |
85 | } |
86 | |
87 | void ShmServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version) |
88 | { |
89 | Q_UNUSED(version); |
90 | if (interface == "qt_shm_emulation_server_buffer" ) { |
91 | auto *integration = static_cast<ShmServerBufferIntegration *>(data); |
92 | integration->QtWayland::qt_shm_emulation_server_buffer::init(registry, id, 1); |
93 | } |
94 | } |
95 | |
96 | |
97 | void QtWaylandClient::ShmServerBufferIntegration::shm_emulation_server_buffer_server_buffer_created(qt_server_buffer *id, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format) |
98 | { |
99 | QSize size(width, height); |
100 | auto fmt = QWaylandServerBuffer::Format(format); |
101 | auto *server_buffer = new ShmServerBuffer(key, size, bytes_per_line, fmt); |
102 | qt_server_buffer_set_user_data(id, server_buffer); |
103 | } |
104 | |
105 | } |
106 | |
107 | QT_END_NAMESPACE |
108 | |