c693450976
The virtual backend uses the surfaceless platform. On the other hand, we move in a direction where the graphics buffer type is explicit, which creates issues for the virtual backend. This change ports the virtual backend to gbm so we could manually allocate dmabuf buffers in order to unify buffer handling in kwin. Its main drawback is that you won't be able to use the virtual backend on setups without render nodes. On the other hand, given that the compositor is meaningless without clients being able to share buffers with it, it's reasonable to require some way to create and export prime buffers.
148 lines
4.8 KiB
C++
148 lines
4.8 KiB
C++
/*
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "kwin_wayland_test.h"
|
|
|
|
#include "composite.h"
|
|
#include "core/output.h"
|
|
#include "core/outputbackend.h"
|
|
#include "core/renderbackend.h"
|
|
#include "effectloader.h"
|
|
#include "effects.h"
|
|
#include "wayland_server.h"
|
|
#include "window.h"
|
|
#include "workspace.h"
|
|
|
|
#include <KWayland/Client/surface.h>
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_dont_crash_reinitialize_compositor-0");
|
|
|
|
class DontCrashReinitializeCompositorTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
void initTestCase();
|
|
void init();
|
|
void cleanup();
|
|
|
|
void testReinitializeCompositor_data();
|
|
void testReinitializeCompositor();
|
|
};
|
|
|
|
void DontCrashReinitializeCompositorTest::initTestCase()
|
|
{
|
|
if (!Test::renderNodeAvailable()) {
|
|
QSKIP("no render node available");
|
|
return;
|
|
}
|
|
qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8());
|
|
|
|
qRegisterMetaType<KWin::Window *>();
|
|
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
|
QVERIFY(waylandServer()->init(s_socketName));
|
|
QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
|
|
|
|
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
|
KConfigGroup plugins(config, QStringLiteral("Plugins"));
|
|
const auto builtinNames = EffectLoader().listOfKnownEffects();
|
|
for (const QString &name : builtinNames) {
|
|
plugins.writeEntry(name + QStringLiteral("Enabled"), false);
|
|
}
|
|
config->sync();
|
|
kwinApp()->setConfig(config);
|
|
|
|
qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2"));
|
|
qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", QByteArrayLiteral("1"));
|
|
|
|
kwinApp()->start();
|
|
QVERIFY(applicationStartedSpy.wait());
|
|
const auto outputs = workspace()->outputs();
|
|
QCOMPARE(outputs.count(), 2);
|
|
QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
|
|
QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
|
|
|
|
QCOMPARE(Compositor::self()->backend()->compositingType(), KWin::OpenGLCompositing);
|
|
}
|
|
|
|
void DontCrashReinitializeCompositorTest::init()
|
|
{
|
|
QVERIFY(Test::setupWaylandConnection());
|
|
}
|
|
|
|
void DontCrashReinitializeCompositorTest::cleanup()
|
|
{
|
|
// Unload all effects.
|
|
auto effectsImpl = qobject_cast<EffectsHandlerImpl *>(effects);
|
|
QVERIFY(effectsImpl);
|
|
effectsImpl->unloadAllEffects();
|
|
QVERIFY(effectsImpl->loadedEffects().isEmpty());
|
|
|
|
Test::destroyWaylandConnection();
|
|
}
|
|
|
|
void DontCrashReinitializeCompositorTest::testReinitializeCompositor_data()
|
|
{
|
|
QTest::addColumn<QString>("effectName");
|
|
|
|
QTest::newRow("Fade") << QStringLiteral("fade");
|
|
QTest::newRow("Glide") << QStringLiteral("glide");
|
|
QTest::newRow("Scale") << QStringLiteral("scale");
|
|
}
|
|
|
|
void DontCrashReinitializeCompositorTest::testReinitializeCompositor()
|
|
{
|
|
// This test verifies that KWin doesn't crash when the compositor settings
|
|
// have been changed while a scripted effect animates the disappearing of
|
|
// a window.
|
|
|
|
// Make sure that we have the right effects ptr.
|
|
auto effectsImpl = qobject_cast<EffectsHandlerImpl *>(effects);
|
|
QVERIFY(effectsImpl);
|
|
|
|
// Create the test window.
|
|
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
|
QVERIFY(surface != nullptr);
|
|
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
|
QVERIFY(shellSurface != nullptr);
|
|
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
|
QVERIFY(window);
|
|
|
|
// Make sure that only the test effect is loaded.
|
|
QFETCH(QString, effectName);
|
|
QVERIFY(effectsImpl->loadEffect(effectName));
|
|
QCOMPARE(effectsImpl->loadedEffects().count(), 1);
|
|
QCOMPARE(effectsImpl->loadedEffects().first(), effectName);
|
|
Effect *effect = effectsImpl->findEffect(effectName);
|
|
QVERIFY(effect);
|
|
QVERIFY(!effect->isActive());
|
|
|
|
// Close the test window.
|
|
QSignalSpy windowClosedSpy(window, &Window::closed);
|
|
shellSurface.reset();
|
|
surface.reset();
|
|
QVERIFY(windowClosedSpy.wait());
|
|
|
|
// The test effect should start animating the test window. Is there a better
|
|
// way to verify that the test effect actually animates the test window?
|
|
QVERIFY(effect->isActive());
|
|
|
|
// Re-initialize the compositor, effects will be destroyed and created again.
|
|
Compositor::self()->reinitialize();
|
|
|
|
// By this time, KWin should still be alive.
|
|
}
|
|
|
|
} // namespace KWin
|
|
|
|
WAYLANDTEST_MAIN(KWin::DontCrashReinitializeCompositorTest)
|
|
#include "dont_crash_reinitialize_compositor.moc"
|