Revision control

++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:critical reason:network-protocol
++
++ #include "shmserverbufferintegration.h"
++
++ #include <QtOpenGL/QOpenGLTexture>
++ #include <QtGui/QOpenGLContext>
++ #include <QtCore/QSharedMemory>
++
++ #include <QtCore/QDebug>
++
++ QT_BEGIN_NAMESPACE
++
++ ShmServerBuffer::ShmServerBuffer(ShmServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
++ : QtWayland::ServerBuffer(qimage.size(),format)
++ , m_integration(integration)
++ , m_width(qimage.width())
++ , m_height(qimage.height())
++ , m_bpl(qimage.bytesPerLine())
++ {
++ m_format = format;
++ switch (m_format) {
++ case RGBA32:
++ m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_RGBA32;
++ break;
++ case A8:
++ m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_A8;
++ break;
++ default:
++ qWarning("ShmServerBuffer: unsupported format");
++ m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_RGBA32;
++ break;
++ }
++
++ QString key = "qt_shm_emulation_" + QString::number(qimage.cacheKey());
++ // ### Use proper native keys the next time we can break protocol compatibility
++ QT_IGNORE_DEPRECATIONS(m_shm = new QSharedMemory(key);)
++ qsizetype shm_size = qimage.sizeInBytes();
++ bool ok = m_shm->create(shm_size) && m_shm->lock();
++ if (ok) {
++ memcpy(m_shm->data(), qimage.constBits(), shm_size);
++ m_shm->unlock();
++ } else {
++ qWarning() << "Could not create shared memory" << key << shm_size;
++ }
++ }
++
++ ShmServerBuffer::~ShmServerBuffer()
++ {
++ delete m_shm;
++ }
++
++ struct ::wl_resource *ShmServerBuffer::resourceForClient(struct ::wl_client *client)
++ {
++ auto *bufferResource = resourceMap().value(client);
++ if (!bufferResource) {
++ auto integrationResource = m_integration->resourceMap().value(client);
++ if (!integrationResource) {
++ qWarning("ShmServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the shm_emulation interface");
++ return nullptr;
++ }
++ struct ::wl_resource *shm_integration_resource = integrationResource->handle;
++ Resource *resource = add(client, 1);
++ QT_IGNORE_DEPRECATIONS(const QString shmKey = m_shm->key();)
++ m_integration->send_server_buffer_created(shm_integration_resource, resource->handle, shmKey, m_width, m_height, m_bpl, m_shm_format);
++ return resource->handle;
++ }
++ return bufferResource->handle;
++ }
++
++ bool ShmServerBuffer::bufferInUse()
++ {
++ return resourceMap().size() > 0;
++ }
++
++ QOpenGLTexture *ShmServerBuffer::toOpenGlTexture()
++ {
++ if (!m_texture) {
++ qWarning("ShmServerBuffer::toOpenGlTexture: no texture defined");
++ }
++ return m_texture;
++ }
++
++ ShmServerBufferIntegration::ShmServerBufferIntegration()
++ {
++ }
++
++ ShmServerBufferIntegration::~ShmServerBufferIntegration()
++ {
++ }
++
++ bool ShmServerBufferIntegration::initializeHardware(QWaylandCompositor *compositor)
++ {
++ Q_ASSERT(QGuiApplication::platformNativeInterface());
++
++ QtWaylandServer::qt_shm_emulation_server_buffer::init(compositor->display(), 1);
++ return true;
++ }
++
++ bool ShmServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Format format) const
++ {
++ switch (format) {
++ case QtWayland::ServerBuffer::RGBA32:
++ return true;
++ case QtWayland::ServerBuffer::A8:
++ return true;
++ default:
++ return false;
++ }
++ }
++
++ QtWayland::ServerBuffer *ShmServerBufferIntegration::createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format)
++ {
++ return new ShmServerBuffer(this, qimage, format);
++ }
++
++ QT_END_NAMESPACE