1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "shmserverbufferintegration.h"
5
6#include <QtOpenGL/QOpenGLTexture>
7#include <QtGui/QOpenGLContext>
8#include <QtCore/QSharedMemory>
9
10#include <QtCore/QDebug>
11
12QT_BEGIN_NAMESPACE
13
14ShmServerBuffer::ShmServerBuffer(ShmServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
15 : QtWayland::ServerBuffer(qimage.size(),format)
16 , m_integration(integration)
17 , m_width(qimage.width())
18 , m_height(qimage.height())
19 , m_bpl(qimage.bytesPerLine())
20{
21 m_format = format;
22 switch (m_format) {
23 case RGBA32:
24 m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_RGBA32;
25 break;
26 case A8:
27 m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_A8;
28 break;
29 default:
30 qWarning(msg: "ShmServerBuffer: unsupported format");
31 m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_RGBA32;
32 break;
33 }
34
35 QString key = "qt_shm_emulation_" + QString::number(qimage.cacheKey());
36 // ### Use proper native keys the next time we can break protocol compatibility
37 QT_IGNORE_DEPRECATIONS(m_shm = new QSharedMemory(key);)
38 qsizetype shm_size = qimage.sizeInBytes();
39 bool ok = m_shm->create(size: shm_size) && m_shm->lock();
40 if (ok) {
41 memcpy(dest: m_shm->data(), src: qimage.constBits(), n: shm_size);
42 m_shm->unlock();
43 } else {
44 qWarning() << "Could not create shared memory" << key << shm_size;
45 }
46}
47
48ShmServerBuffer::~ShmServerBuffer()
49{
50 delete m_shm;
51}
52
53struct ::wl_resource *ShmServerBuffer::resourceForClient(struct ::wl_client *client)
54{
55 auto *bufferResource = resourceMap().value(client);
56 if (!bufferResource) {
57 auto integrationResource = m_integration->resourceMap().value(client);
58 if (!integrationResource) {
59 qWarning(msg: "ShmServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the shm_emulation interface");
60 return nullptr;
61 }
62 struct ::wl_resource *shm_integration_resource = integrationResource->handle;
63 Resource *resource = add(client, 1);
64 QT_IGNORE_DEPRECATIONS(const QString shmKey = m_shm->key();)
65 m_integration->send_server_buffer_created(shm_integration_resource, resource->handle, shmKey, m_width, m_height, m_bpl, m_shm_format);
66 return resource->handle;
67 }
68 return bufferResource->handle;
69}
70
71bool ShmServerBuffer::bufferInUse()
72{
73 return resourceMap().size() > 0;
74}
75
76QOpenGLTexture *ShmServerBuffer::toOpenGlTexture()
77{
78 if (!m_texture) {
79 qWarning(msg: "ShmServerBuffer::toOpenGlTexture: no texture defined");
80 }
81 return m_texture;
82}
83
84ShmServerBufferIntegration::ShmServerBufferIntegration()
85{
86}
87
88ShmServerBufferIntegration::~ShmServerBufferIntegration()
89{
90}
91
92bool ShmServerBufferIntegration::initializeHardware(QWaylandCompositor *compositor)
93{
94 Q_ASSERT(QGuiApplication::platformNativeInterface());
95
96 QtWaylandServer::qt_shm_emulation_server_buffer::init(compositor->display(), 1);
97 return true;
98}
99
100bool ShmServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Format format) const
101{
102 switch (format) {
103 case QtWayland::ServerBuffer::RGBA32:
104 return true;
105 case QtWayland::ServerBuffer::A8:
106 return true;
107 default:
108 return false;
109 }
110}
111
112QtWayland::ServerBuffer *ShmServerBufferIntegration::createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format)
113{
114 return new ShmServerBuffer(this, qimage, format);
115}
116
117QT_END_NAMESPACE
118

source code of qtwayland/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp