From 06f64d5e567e951ffe355f4b12af8ba3f83225b8 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Thu, 21 Feb 2019 23:25:19 +0100 Subject: [PATCH] [autotests] Sub-surface resize test Summary: Adds an autotest to show that KWin fails an assertion when a client tries to resize a sub-surface. Since it is the first autotest dealing with sub-surfaces explicitly additional autotest helpers are introduced to allow that. We also add a new signal in Compositor to spy on to know when the buffer swap has been completed. Test Plan: Test fails as expected: ``` QFATAL : KWin::BufferSizeChangeTest::testShmBufferSizeChangeOnSubSurface() ASSERT: "image.size() == m_size" in file /home/roman/dev/kde/src/kde/workspace/kwin/platformsupport/scenes/opengl/abstract_egl_backend.cpp, line 394 FAIL! : KWin::BufferSizeChangeTest::testShmBufferSizeChangeOnSubSurface() Received a fatal error. Loc: [Unknown file(0)] Totals: 4 passed, 1 failed, 0 skipped, 0 blacklisted, 367ms ********* Finished testing of KWin::BufferSizeChangeTest ********* ``` Reviewers: #kwin, zzag Subscribers: zzag, graesslin, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D18452 --- autotests/integration/CMakeLists.txt | 1 + .../integration/buffer_size_change_test.cpp | 128 ++++++++++++++++++ autotests/integration/kwin_wayland_test.h | 5 + autotests/integration/test_helpers.cpp | 27 ++++ composite.cpp | 2 + composite.h | 1 + 6 files changed, 164 insertions(+) create mode 100644 autotests/integration/buffer_size_change_test.cpp diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt index 0a63c85fea..78bbe46933 100644 --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -59,6 +59,7 @@ integrationTest(WAYLAND_ONLY NAME testColorCorrectNightColor SRCS colorcorrect_n integrationTest(WAYLAND_ONLY NAME testDontCrashCursorPhysicalSizeEmpty SRCS dont_crash_cursor_physical_size_empty.cpp) integrationTest(WAYLAND_ONLY NAME testDontCrashReinitializeCompositor SRCS dont_crash_reinitialize_compositor.cpp) integrationTest(WAYLAND_ONLY NAME testNoGlobalShortcuts SRCS no_global_shortcuts_test.cpp) +integrationTest(WAYLAND_ONLY NAME testBufferSizeChange SRCS buffer_size_change_test.cpp generic_scene_opengl_test.cpp) if (XCB_ICCCM_FOUND) integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM) diff --git a/autotests/integration/buffer_size_change_test.cpp b/autotests/integration/buffer_size_change_test.cpp new file mode 100644 index 0000000000..4c5231a7c4 --- /dev/null +++ b/autotests/integration/buffer_size_change_test.cpp @@ -0,0 +1,128 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright 2019 Roman Gilg + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "generic_scene_opengl_test.h" + +#include "composite.h" +#include "shell_client.h" +#include "wayland_server.h" + +#include +#include +#include + +namespace KWin +{ + +static const QString s_socketName = QStringLiteral("wayland_test_buffer_size_change-0"); + +class BufferSizeChangeTest : public GenericSceneOpenGLTest +{ + Q_OBJECT +public: + BufferSizeChangeTest() : GenericSceneOpenGLTest(QByteArrayLiteral("O2")) {} +private Q_SLOTS: + void init(); + void testShmBufferSizeChange(); + void testShmBufferSizeChangeOnSubSurface(); +}; + +void BufferSizeChangeTest::init() +{ + QVERIFY(Test::setupWaylandConnection()); +} + +void BufferSizeChangeTest::testShmBufferSizeChange() +{ + // This test verifies that an SHM buffer size change is handled correctly + + using namespace KWayland::Client; + + QScopedPointer surface(Test::createSurface()); + QVERIFY(!surface.isNull()); + + QScopedPointer shellSurface(Test::createXdgShellStableSurface(surface.data())); + QVERIFY(!shellSurface.isNull()); + Test::flushWaylandConnection(); + + // set buffer size + ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue); + QVERIFY(client); + + // add a first repaint + QSignalSpy swapSpy(Compositor::self(), &Compositor::bufferSwapCompleted); + QVERIFY(swapSpy.isValid()); + Compositor::self()->addRepaintFull(); + QVERIFY(swapSpy.wait()); + + // now change buffer size + Test::render(surface.data(), QSize(30, 10), Qt::red); + Test::flushWaylandConnection(); + + QSignalSpy damagedSpy(client, &ShellClient::damaged); + QVERIFY(damagedSpy.isValid()); + QVERIFY(damagedSpy.wait()); + KWin::Compositor::self()->addRepaintFull(); + QVERIFY(swapSpy.wait()); +} + +void BufferSizeChangeTest::testShmBufferSizeChangeOnSubSurface() +{ + using namespace KWayland::Client; + + // setup parent surface + QScopedPointer parentSurface(Test::createSurface()); + QVERIFY(!parentSurface.isNull()); + QScopedPointer shellSurface(Test::createXdgShellStableSurface(parentSurface.data())); + QVERIFY(!shellSurface.isNull()); + + // setup sub surface + QScopedPointer surface(Test::createSurface()); + QVERIFY(!surface.isNull()); + QScopedPointer subSurface(Test::createSubSurface(surface.data(), parentSurface.data())); + QVERIFY(!subSurface.isNull()); + + // set buffer sizes + Test::render(surface.data(), QSize(30, 10), Qt::red); + ShellClient *parent = Test::renderAndWaitForShown(parentSurface.data(), QSize(100, 50), Qt::blue); + QVERIFY(parent); + + // add a first repaint + QSignalSpy swapSpy(Compositor::self(), &Compositor::bufferSwapCompleted); + QVERIFY(swapSpy.isValid()); + Compositor::self()->addRepaintFull(); + QVERIFY(swapSpy.wait()); + + // change buffer size of sub surface + QSignalSpy damagedParentSpy(parent, &ShellClient::damaged); + QVERIFY(damagedParentSpy.isValid()); + Test::render(surface.data(), QSize(20, 10), Qt::red); + parentSurface->commit(Surface::CommitFlag::None); + + QVERIFY(damagedParentSpy.wait()); + + // add a second repaint + KWin::Compositor::self()->addRepaintFull(); + QVERIFY(swapSpy.wait()); +} + +} + +WAYLANDTEST_MAIN(KWin::BufferSizeChangeTest) +#include "buffer_size_change_test.moc" diff --git a/autotests/integration/kwin_wayland_test.h b/autotests/integration/kwin_wayland_test.h index 2a8db8c0d0..c764b362ec 100644 --- a/autotests/integration/kwin_wayland_test.h +++ b/autotests/integration/kwin_wayland_test.h @@ -45,6 +45,8 @@ class ShadowManager; class Shell; class ShellSurface; class ShmPool; +class SubCompositor; +class SubSurface; class Surface; class XdgDecorationManager; } @@ -112,6 +114,7 @@ void destroyWaylandConnection(); KWayland::Client::ConnectionThread *waylandConnection(); KWayland::Client::Compositor *waylandCompositor(); +KWayland::Client::SubCompositor *waylandSubCompositor(); KWayland::Client::ShadowManager *waylandShadowManager(); KWayland::Client::Shell *waylandShell(); KWayland::Client::ShmPool *waylandShmPool(); @@ -131,6 +134,8 @@ bool waitForWaylandKeyboard(); void flushWaylandConnection(); KWayland::Client::Surface *createSurface(QObject *parent = nullptr); +KWayland::Client::SubSurface *createSubSurface(KWayland::Client::Surface *surface, + KWayland::Client::Surface *parentSurface, QObject *parent = nullptr); enum class ShellSurfaceType { WlShell, XdgShellV5, diff --git a/autotests/integration/test_helpers.cpp b/autotests/integration/test_helpers.cpp index 72405a56cd..cde024f622 100644 --- a/autotests/integration/test_helpers.cpp +++ b/autotests/integration/test_helpers.cpp @@ -36,6 +36,8 @@ along with this program. If not, see . #include #include #include +#include +#include #include #include #include @@ -63,6 +65,7 @@ static struct { ConnectionThread *connection = nullptr; EventQueue *queue = nullptr; Compositor *compositor = nullptr; + SubCompositor *subCompositor = nullptr; ServerSideDecorationManager *decoration = nullptr; ShadowManager *shadowManager = nullptr; Shell *shell = nullptr; @@ -146,6 +149,10 @@ bool setupWaylandConnection(AdditionalWaylandInterfaces flags) if (!s_waylandConnection.compositor->isValid()) { return false; } + s_waylandConnection.subCompositor = registry->createSubCompositor(registry->interface(Registry::Interface::SubCompositor).name, registry->interface(Registry::Interface::SubCompositor).version); + if (!s_waylandConnection.subCompositor->isValid()) { + return false; + } s_waylandConnection.shm = registry->createShmPool(registry->interface(Registry::Interface::Shm).name, registry->interface(Registry::Interface::Shm).version); if (!s_waylandConnection.shm->isValid()) { return false; @@ -234,6 +241,8 @@ void destroyWaylandConnection() { delete s_waylandConnection.compositor; s_waylandConnection.compositor = nullptr; + delete s_waylandConnection.subCompositor; + s_waylandConnection.subCompositor = nullptr; delete s_waylandConnection.windowManagement; s_waylandConnection.windowManagement = nullptr; delete s_waylandConnection.plasmaShell; @@ -292,6 +301,11 @@ Compositor *waylandCompositor() return s_waylandConnection.compositor; } +SubCompositor *waylandSubCompositor() +{ + return s_waylandConnection.subCompositor; +} + ShadowManager *waylandShadowManager() { return s_waylandConnection.shadowManager; @@ -444,6 +458,19 @@ Surface *createSurface(QObject *parent) return s; } +SubSurface *createSubSurface(Surface *surface, Surface *parentSurface, QObject *parent) +{ + if (!s_waylandConnection.subCompositor) { + return nullptr; + } + auto s = s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface, parent); + if (!s->isValid()) { + delete s; + return nullptr; + } + return s; +} + ShellSurface *createShellSurface(Surface *surface, QObject *parent) { if (!s_waylandConnection.shell) { diff --git a/composite.cpp b/composite.cpp index f369a4e244..5fd3a31066 100644 --- a/composite.cpp +++ b/composite.cpp @@ -655,6 +655,8 @@ void Compositor::bufferSwapComplete() assert(m_bufferSwapPending); m_bufferSwapPending = false; + emit bufferSwapCompleted(); + if (m_composeAtSwapCompletion) { m_composeAtSwapCompletion = false; performCompositing(); diff --git a/composite.h b/composite.h index 12c7db3640..c9fac40bfc 100644 --- a/composite.h +++ b/composite.h @@ -178,6 +178,7 @@ Q_SIGNALS: void aboutToDestroy(); void aboutToToggleCompositing(); void sceneCreated(); + void bufferSwapCompleted(); protected: void timerEvent(QTimerEvent *te);