File indexing completed on 2024-11-10 04:56:17

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 // Qt
0007 #include <QImage>
0008 #include <QSignalSpy>
0009 #include <QTest>
0010 // KWin
0011 #include "wayland/compositor.h"
0012 #include "wayland/display.h"
0013 #include "wayland/surface.h"
0014 
0015 #include "KWayland/Client/compositor.h"
0016 #include "KWayland/Client/connection_thread.h"
0017 #include "KWayland/Client/registry.h"
0018 #include "KWayland/Client/shm_pool.h"
0019 #include "KWayland/Client/surface.h"
0020 
0021 class TestShmPool : public QObject
0022 {
0023     Q_OBJECT
0024 public:
0025     explicit TestShmPool(QObject *parent = nullptr);
0026 private Q_SLOTS:
0027     void init();
0028     void cleanup();
0029 
0030     void testCreateBufferNullImage();
0031     void testCreateBufferNullSize();
0032     void testCreateBufferInvalidSize();
0033     void testCreateBufferFromImage();
0034     void testCreateBufferFromImageWithAlpha();
0035     void testCreateBufferFromData();
0036     void testReuseBuffer();
0037 
0038 private:
0039     KWin::Display *m_display;
0040     KWayland::Client::ConnectionThread *m_connection;
0041     KWayland::Client::Compositor *m_compositor;
0042     KWayland::Client::ShmPool *m_shmPool;
0043     QThread *m_thread;
0044 };
0045 
0046 static const QString s_socketName = QStringLiteral("kwin-test-wayland-surface-0");
0047 
0048 TestShmPool::TestShmPool(QObject *parent)
0049     : QObject(parent)
0050     , m_display(nullptr)
0051     , m_connection(nullptr)
0052     , m_compositor(nullptr)
0053     , m_shmPool(nullptr)
0054     , m_thread(nullptr)
0055 {
0056 }
0057 
0058 void TestShmPool::init()
0059 {
0060     using namespace KWin;
0061     delete m_display;
0062     m_display = new KWin::Display(this);
0063     m_display->addSocketName(s_socketName);
0064     m_display->start();
0065     QVERIFY(m_display->isRunning());
0066 
0067     // setup connection
0068     m_connection = new KWayland::Client::ConnectionThread;
0069     QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
0070     m_connection->setSocketName(s_socketName);
0071 
0072     m_thread = new QThread(this);
0073     m_connection->moveToThread(m_thread);
0074     m_thread->start();
0075 
0076     m_connection->initConnection();
0077     QVERIFY(connectedSpy.wait());
0078 
0079     KWayland::Client::Registry registry;
0080     QSignalSpy shmSpy(&registry, &KWayland::Client::Registry::shmAnnounced);
0081     registry.create(m_connection->display());
0082     QVERIFY(registry.isValid());
0083     registry.setup();
0084 
0085     // here we need a shm pool
0086     m_display->createShm();
0087 
0088     QVERIFY(shmSpy.wait());
0089     m_shmPool = registry.createShmPool(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>(), this);
0090 }
0091 
0092 void TestShmPool::cleanup()
0093 {
0094     if (m_compositor) {
0095         delete m_compositor;
0096         m_compositor = nullptr;
0097     }
0098     if (m_shmPool) {
0099         delete m_shmPool;
0100         m_shmPool = nullptr;
0101     }
0102     if (m_thread) {
0103         m_thread->quit();
0104         m_thread->wait();
0105         delete m_thread;
0106         m_thread = nullptr;
0107     }
0108     delete m_connection;
0109     m_connection = nullptr;
0110 
0111     delete m_display;
0112     m_display = nullptr;
0113 }
0114 
0115 void TestShmPool::testCreateBufferNullImage()
0116 {
0117     QVERIFY(m_shmPool->isValid());
0118     QImage img;
0119     QVERIFY(img.isNull());
0120     QVERIFY(!m_shmPool->createBuffer(img));
0121 }
0122 
0123 void TestShmPool::testCreateBufferNullSize()
0124 {
0125     QVERIFY(m_shmPool->isValid());
0126     QSize size(0, 0);
0127     QVERIFY(size.isNull());
0128     QVERIFY(!m_shmPool->createBuffer(size, 0, nullptr));
0129 }
0130 
0131 void TestShmPool::testCreateBufferInvalidSize()
0132 {
0133     QVERIFY(m_shmPool->isValid());
0134     QSize size;
0135     QVERIFY(!size.isValid());
0136     QVERIFY(!m_shmPool->createBuffer(size, 0, nullptr));
0137 }
0138 
0139 void TestShmPool::testCreateBufferFromImage()
0140 {
0141     QVERIFY(m_shmPool->isValid());
0142     QImage img(24, 24, QImage::Format_RGB32);
0143     img.fill(Qt::black);
0144     QVERIFY(!img.isNull());
0145     auto buffer = m_shmPool->createBuffer(img).toStrongRef();
0146     QVERIFY(buffer);
0147     QCOMPARE(buffer->size(), img.size());
0148     QImage img2(buffer->address(), img.width(), img.height(), QImage::Format_RGB32);
0149     QCOMPARE(img2, img);
0150 }
0151 
0152 void TestShmPool::testCreateBufferFromImageWithAlpha()
0153 {
0154     QVERIFY(m_shmPool->isValid());
0155     QImage img(24, 24, QImage::Format_ARGB32_Premultiplied);
0156     img.fill(QColor(255, 0, 0, 100)); // red with alpha
0157     QVERIFY(!img.isNull());
0158     auto buffer = m_shmPool->createBuffer(img).toStrongRef();
0159     QVERIFY(buffer);
0160     QCOMPARE(buffer->size(), img.size());
0161     QImage img2(buffer->address(), img.width(), img.height(), QImage::Format_ARGB32_Premultiplied);
0162     QCOMPARE(img2, img);
0163 }
0164 
0165 void TestShmPool::testCreateBufferFromData()
0166 {
0167     QVERIFY(m_shmPool->isValid());
0168     QImage img(24, 24, QImage::Format_ARGB32_Premultiplied);
0169     img.fill(Qt::black);
0170     QVERIFY(!img.isNull());
0171     auto buffer = m_shmPool->createBuffer(img.size(), img.bytesPerLine(), img.constBits()).toStrongRef();
0172     QVERIFY(buffer);
0173     QCOMPARE(buffer->size(), img.size());
0174     QImage img2(buffer->address(), img.width(), img.height(), QImage::Format_ARGB32_Premultiplied);
0175     QCOMPARE(img2, img);
0176 }
0177 
0178 void TestShmPool::testReuseBuffer()
0179 {
0180     QVERIFY(m_shmPool->isValid());
0181     QImage img(24, 24, QImage::Format_ARGB32_Premultiplied);
0182     img.fill(Qt::black);
0183     QVERIFY(!img.isNull());
0184     auto buffer = m_shmPool->createBuffer(img).toStrongRef();
0185     QVERIFY(buffer);
0186     buffer->setReleased(true);
0187     buffer->setUsed(false);
0188 
0189     // same image should get the same buffer
0190     auto buffer2 = m_shmPool->createBuffer(img).toStrongRef();
0191     QCOMPARE(buffer, buffer2);
0192     buffer2->setReleased(true);
0193     buffer2->setUsed(false);
0194 
0195     // image with different size should get us a new buffer
0196     auto buffer3 = m_shmPool->getBuffer(QSize(10, 10), 8);
0197     QVERIFY(buffer3 != buffer2);
0198 
0199     // image with a different format should get us a new buffer
0200     QImage img2(24, 24, QImage::Format_RGB32);
0201     img2.fill(Qt::black);
0202     QVERIFY(!img2.isNull());
0203     auto buffer4 = m_shmPool->createBuffer(img2).toStrongRef();
0204     QVERIFY(buffer4);
0205     QVERIFY(buffer4 != buffer2);
0206     QVERIFY(buffer4 != buffer3);
0207 }
0208 
0209 QTEST_GUILESS_MAIN(TestShmPool)
0210 #include "test_shm_pool.moc"