Move X11Compositor and WaylandCompositor in their own files
parent
14ab38b596
commit
6dd6e176e3
@ -0,0 +1,60 @@
|
||||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "compositor_wayland.h"
|
||||
#include "main.h"
|
||||
#include "workspace.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
WaylandCompositor *WaylandCompositor::create(QObject *parent)
|
||||
{
|
||||
Q_ASSERT(!s_compositor);
|
||||
auto *compositor = new WaylandCompositor(parent);
|
||||
s_compositor = compositor;
|
||||
return compositor;
|
||||
}
|
||||
|
||||
WaylandCompositor::WaylandCompositor(QObject *parent)
|
||||
: Compositor(parent)
|
||||
{
|
||||
connect(kwinApp(), &Application::x11ConnectionAboutToBeDestroyed,
|
||||
this, &WaylandCompositor::destroyCompositorSelection);
|
||||
}
|
||||
|
||||
WaylandCompositor::~WaylandCompositor()
|
||||
{
|
||||
Q_EMIT aboutToDestroy();
|
||||
stop(); // this can't be called in the destructor of Compositor
|
||||
}
|
||||
|
||||
void WaylandCompositor::toggleCompositing()
|
||||
{
|
||||
// For the shortcut. Not possible on Wayland because we always composite.
|
||||
}
|
||||
|
||||
void WaylandCompositor::start()
|
||||
{
|
||||
if (!Compositor::setupStart()) {
|
||||
// Internal setup failed, abort.
|
||||
return;
|
||||
}
|
||||
|
||||
if (Workspace::self()) {
|
||||
startupWithWorkspace();
|
||||
} else {
|
||||
connect(kwinApp(), &Application::workspaceCreated,
|
||||
this, &WaylandCompositor::startupWithWorkspace);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#include "moc_compositor_wayland.cpp"
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de>
|
||||
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class KWIN_EXPORT WaylandCompositor final : public Compositor
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static WaylandCompositor *create(QObject *parent = nullptr);
|
||||
~WaylandCompositor() override;
|
||||
|
||||
void toggleCompositing() override;
|
||||
|
||||
protected:
|
||||
void start() override;
|
||||
|
||||
private:
|
||||
explicit WaylandCompositor(QObject *parent);
|
||||
};
|
||||
|
||||
} // namespace KWin
|
@ -0,0 +1,398 @@
|
||||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "compositor_x11.h"
|
||||
#include "core/overlaywindow.h"
|
||||
#include "core/renderbackend.h"
|
||||
#include "options.h"
|
||||
#include "scene/surfaceitem_x11.h"
|
||||
#include "utils/common.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "workspace.h"
|
||||
#include "x11syncmanager.h"
|
||||
#include "x11window.h"
|
||||
|
||||
#include <KCrash>
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
#if KWIN_BUILD_NOTIFICATIONS
|
||||
#include <KNotification>
|
||||
#endif
|
||||
|
||||
#include <QAction>
|
||||
#include <QOpenGLContext>
|
||||
#include <QThread>
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::X11Compositor::SuspendReason)
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
X11Compositor *X11Compositor::create(QObject *parent)
|
||||
{
|
||||
Q_ASSERT(!s_compositor);
|
||||
auto *compositor = new X11Compositor(parent);
|
||||
s_compositor = compositor;
|
||||
return compositor;
|
||||
}
|
||||
|
||||
X11Compositor::X11Compositor(QObject *parent)
|
||||
: Compositor(parent)
|
||||
, m_suspended(options->isUseCompositing() ? NoReasonSuspend : UserSuspend)
|
||||
{
|
||||
if (qEnvironmentVariableIsSet("KWIN_MAX_FRAMES_TESTED")) {
|
||||
m_framesToTestForSafety = qEnvironmentVariableIntValue("KWIN_MAX_FRAMES_TESTED");
|
||||
}
|
||||
}
|
||||
|
||||
X11Compositor::~X11Compositor()
|
||||
{
|
||||
Q_EMIT aboutToDestroy();
|
||||
if (m_openGLFreezeProtectionThread) {
|
||||
m_openGLFreezeProtectionThread->quit();
|
||||
m_openGLFreezeProtectionThread->wait();
|
||||
}
|
||||
stop(); // this can't be called in the destructor of Compositor
|
||||
}
|
||||
|
||||
X11SyncManager *X11Compositor::syncManager() const
|
||||
{
|
||||
return m_syncManager.get();
|
||||
}
|
||||
|
||||
void X11Compositor::toggleCompositing()
|
||||
{
|
||||
if (m_suspended) {
|
||||
// Direct user call; clear all bits.
|
||||
resume(AllReasonSuspend);
|
||||
} else {
|
||||
// But only set the user one (sufficient to suspend).
|
||||
suspend(UserSuspend);
|
||||
}
|
||||
}
|
||||
|
||||
void X11Compositor::reinitialize()
|
||||
{
|
||||
// Resume compositing if suspended.
|
||||
m_suspended = NoReasonSuspend;
|
||||
Compositor::reinitialize();
|
||||
}
|
||||
|
||||
void X11Compositor::configChanged()
|
||||
{
|
||||
if (m_suspended) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
Compositor::configChanged();
|
||||
}
|
||||
|
||||
void X11Compositor::suspend(X11Compositor::SuspendReason reason)
|
||||
{
|
||||
Q_ASSERT(reason != NoReasonSuspend);
|
||||
m_suspended |= reason;
|
||||
|
||||
if (reason & ScriptSuspend) {
|
||||
// When disabled show a shortcut how the user can get back compositing.
|
||||
const auto shortcuts = KGlobalAccel::self()->shortcut(workspace()->findChild<QAction *>(QStringLiteral("Suspend Compositing")));
|
||||
if (!shortcuts.isEmpty()) {
|
||||
// Display notification only if there is the shortcut.
|
||||
const QString message =
|
||||
i18n("Desktop effects have been suspended by another application.<br/>"
|
||||
"You can resume using the '%1' shortcut.",
|
||||
shortcuts.first().toString(QKeySequence::NativeText));
|
||||
#if KWIN_BUILD_NOTIFICATIONS
|
||||
KNotification::event(QStringLiteral("compositingsuspendeddbus"), message);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
void X11Compositor::resume(X11Compositor::SuspendReason reason)
|
||||
{
|
||||
Q_ASSERT(reason != NoReasonSuspend);
|
||||
m_suspended &= ~reason;
|
||||
start();
|
||||
}
|
||||
|
||||
void X11Compositor::start()
|
||||
{
|
||||
if (m_suspended) {
|
||||
QStringList reasons;
|
||||
if (m_suspended & UserSuspend) {
|
||||
reasons << QStringLiteral("Disabled by User");
|
||||
}
|
||||
if (m_suspended & BlockRuleSuspend) {
|
||||
reasons << QStringLiteral("Disabled by Window");
|
||||
}
|
||||
if (m_suspended & ScriptSuspend) {
|
||||
reasons << QStringLiteral("Disabled by Script");
|
||||
}
|
||||
qCInfo(KWIN_CORE) << "Compositing is suspended, reason:" << reasons;
|
||||
return;
|
||||
} else if (!compositingPossible()) {
|
||||
qCWarning(KWIN_CORE) << "Compositing is not possible";
|
||||
return;
|
||||
}
|
||||
if (!Compositor::setupStart()) {
|
||||
// Internal setup failed, abort.
|
||||
return;
|
||||
}
|
||||
startupWithWorkspace();
|
||||
m_syncManager.reset(X11SyncManager::create());
|
||||
}
|
||||
|
||||
void X11Compositor::stop()
|
||||
{
|
||||
m_syncManager.reset();
|
||||
Compositor::stop();
|
||||
}
|
||||
|
||||
void X11Compositor::composite(RenderLoop *renderLoop)
|
||||
{
|
||||
if (backend()->overlayWindow() && !isOverlayWindowVisible()) {
|
||||
// Return since nothing is visible.
|
||||
return;
|
||||
}
|
||||
|
||||
QList<Window *> windows = workspace()->stackingOrder();
|
||||
QList<SurfaceItemX11 *> dirtyItems;
|
||||
|
||||
// Reset the damage state of each window and fetch the damage region
|
||||
// without waiting for a reply
|
||||
for (Window *window : std::as_const(windows)) {
|
||||
SurfaceItemX11 *surfaceItem = static_cast<SurfaceItemX11 *>(window->surfaceItem());
|
||||
if (surfaceItem->fetchDamage()) {
|
||||
dirtyItems.append(surfaceItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyItems.count() > 0) {
|
||||
if (m_syncManager) {
|
||||
m_syncManager->triggerFence();
|
||||
}
|
||||
xcb_flush(kwinApp()->x11Connection());
|
||||
}
|
||||
|
||||
// Get the replies
|
||||
for (SurfaceItemX11 *item : std::as_const(dirtyItems)) {
|
||||
item->waitForDamage();
|
||||
}
|
||||
|
||||
if (m_framesToTestForSafety > 0 && (backend()->compositingType() & OpenGLCompositing)) {
|
||||
createOpenGLSafePoint(OpenGLSafePoint::PreFrame);
|
||||
}
|
||||
|
||||
Compositor::composite(renderLoop);
|
||||
|
||||
if (m_syncManager) {
|
||||
if (!m_syncManager->endFrame()) {
|
||||
qCDebug(KWIN_CORE) << "Aborting explicit synchronization with the X command stream.";
|
||||
qCDebug(KWIN_CORE) << "Future frames will be rendered unsynchronized.";
|
||||
m_syncManager.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_framesToTestForSafety > 0) {
|
||||
if (backend()->compositingType() & OpenGLCompositing) {
|
||||
createOpenGLSafePoint(OpenGLSafePoint::PostFrame);
|
||||
}
|
||||
m_framesToTestForSafety--;
|
||||
if (m_framesToTestForSafety == 0 && (backend()->compositingType() & OpenGLCompositing)) {
|
||||
createOpenGLSafePoint(OpenGLSafePoint::PostLastGuardedFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool X11Compositor::checkForOverlayWindow(WId w) const
|
||||
{
|
||||
if (!backend()) {
|
||||
// No backend, so it cannot be the overlay window.
|
||||
return false;
|
||||
}
|
||||
if (!backend()->overlayWindow()) {
|
||||
// No overlay window, it cannot be the overlay.
|
||||
return false;
|
||||
}
|
||||
// Compare the window ID's.
|
||||
return w == backend()->overlayWindow()->window();
|
||||
}
|
||||
|
||||
bool X11Compositor::isOverlayWindowVisible() const
|
||||
{
|
||||
if (!backend()) {
|
||||
return false;
|
||||
}
|
||||
if (!backend()->overlayWindow()) {
|
||||
return false;
|
||||
}
|
||||
return backend()->overlayWindow()->isVisible();
|
||||
}
|
||||
|
||||
void X11Compositor::updateClientCompositeBlocking(X11Window *c)
|
||||
{
|
||||
if (c) {
|
||||
if (c->isBlockingCompositing()) {
|
||||
// Do NOT attempt to call suspend(true) from within the eventchain!
|
||||
if (!(m_suspended & BlockRuleSuspend)) {
|
||||
QMetaObject::invokeMethod(
|
||||
this, [this]() {
|
||||
suspend(BlockRuleSuspend);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
} else if (m_suspended & BlockRuleSuspend) {
|
||||
// If !c we just check if we can resume in case a blocking client was lost.
|
||||
bool shouldResume = true;
|
||||
|
||||
const auto windows = workspace()->windows();
|
||||
for (Window *window : windows) {
|
||||
X11Window *x11Window = qobject_cast<X11Window *>(window);
|
||||
if (x11Window && x11Window->isBlockingCompositing()) {
|
||||
shouldResume = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shouldResume) {
|
||||
// Do NOT attempt to call suspend(false) from within the eventchain!
|
||||
QMetaObject::invokeMethod(
|
||||
this, [this]() {
|
||||
resume(BlockRuleSuspend);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
X11Compositor *X11Compositor::self()
|
||||
{
|
||||
return qobject_cast<X11Compositor *>(Compositor::self());
|
||||
}
|
||||
|
||||
bool X11Compositor::openGLCompositingIsBroken() const
|
||||
{
|
||||
auto timestamp = KConfigGroup(kwinApp()->config(), "Compositing").readEntry(QLatin1String("LastFailureTimestamp"), 0);
|
||||
if (timestamp > 0) {
|
||||
if (QDateTime::currentSecsSinceEpoch() - timestamp < 60) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString X11Compositor::compositingNotPossibleReason() const
|
||||
{
|
||||
// first off, check whether we figured that we'll crash on detection because of a buggy driver
|
||||
KConfigGroup gl_workaround_group(kwinApp()->config(), "Compositing");
|
||||
if (gl_workaround_group.readEntry("Backend", "OpenGL") == QLatin1String("OpenGL") && openGLCompositingIsBroken()) {
|
||||
return i18n("<b>OpenGL compositing (the default) has crashed KWin in the past.</b><br>"
|
||||
"This was most likely due to a driver bug."
|
||||
"<p>If you think that you have meanwhile upgraded to a stable driver,<br>"
|
||||
"you can reset this protection but <b>be aware that this might result in an immediate crash!</b></p>");
|
||||
}
|
||||
|
||||
if (!Xcb::Extensions::self()->isCompositeAvailable() || !Xcb::Extensions::self()->isDamageAvailable()) {
|
||||
return i18n("Required X extensions (XComposite and XDamage) are not available.");
|
||||
}
|
||||
if (!Xcb::Extensions::self()->hasGlx()) {
|
||||
return i18n("GLX/OpenGL is not available.");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool X11Compositor::compositingPossible() const
|
||||
{
|
||||
// first off, check whether we figured that we'll crash on detection because of a buggy driver
|
||||
KConfigGroup gl_workaround_group(kwinApp()->config(), "Compositing");
|
||||
if (gl_workaround_group.readEntry("Backend", "OpenGL") == QLatin1String("OpenGL") && openGLCompositingIsBroken()) {
|
||||
qCWarning(KWIN_CORE) << "Compositing disabled: video driver seems unstable. If you think it's a false positive, please try again in a few minutes.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Xcb::Extensions::self()->isCompositeAvailable()) {
|
||||
qCWarning(KWIN_CORE) << "Compositing disabled: no composite extension available";
|
||||
return false;
|
||||
}
|
||||
if (!Xcb::Extensions::self()->isDamageAvailable()) {
|
||||
qCWarning(KWIN_CORE) << "Compositing disabled: no damage extension available";
|
||||
return false;
|
||||
}
|
||||
if (Xcb::Extensions::self()->hasGlx()) {
|
||||
return true;
|
||||
}
|
||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
|
||||
return true;
|
||||
} else if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) {
|
||||
return true;
|
||||
}
|
||||
qCWarning(KWIN_CORE) << "Compositing disabled: no OpenGL support";
|
||||
return false;
|
||||
}
|
||||
|
||||
void X11Compositor::createOpenGLSafePoint(OpenGLSafePoint safePoint)
|
||||
{
|
||||
auto group = KConfigGroup(kwinApp()->config(), "Compositing");
|
||||
switch (safePoint) {
|
||||
case OpenGLSafePoint::PreInit:
|
||||
// Explicitly write the failure timestamp so that if we crash during
|
||||
// OpenGL init, we know we should not try again.
|
||||
group.writeEntry(QLatin1String("LastFailureTimestamp"), QDateTime::currentSecsSinceEpoch());
|
||||
group.sync();
|
||||
// Deliberately continue with PreFrame
|
||||
Q_FALLTHROUGH();
|
||||
case OpenGLSafePoint::PreFrame:
|
||||
if (m_openGLFreezeProtectionThread == nullptr) {
|
||||
Q_ASSERT(m_openGLFreezeProtection == nullptr);
|
||||
m_openGLFreezeProtectionThread = std::make_unique<QThread>();
|
||||
m_openGLFreezeProtectionThread->setObjectName("FreezeDetector");
|
||||
m_openGLFreezeProtectionThread->start();
|
||||
m_openGLFreezeProtection = std::make_unique<QTimer>();
|
||||
m_openGLFreezeProtection->setInterval(15000);
|
||||
m_openGLFreezeProtection->setSingleShot(true);
|
||||
m_openGLFreezeProtection->start();
|
||||
const QString configName = kwinApp()->config()->name();
|
||||
m_openGLFreezeProtection->moveToThread(m_openGLFreezeProtectionThread.get());
|
||||
connect(
|
||||
m_openGLFreezeProtection.get(), &QTimer::timeout, m_openGLFreezeProtection.get(),
|
||||
[configName] {
|
||||
auto group = KConfigGroup(KSharedConfig::openConfig(configName), "Compositing");
|
||||
group.writeEntry(QLatin1String("LastFailureTimestamp"), QDateTime::currentSecsSinceEpoch());
|
||||
group.sync();
|
||||
KCrash::setDrKonqiEnabled(false);
|
||||
qFatal("Freeze in OpenGL initialization detected");
|
||||
},
|
||||
Qt::DirectConnection);
|
||||
} else {
|
||||
Q_ASSERT(m_openGLFreezeProtection);
|
||||
QMetaObject::invokeMethod(m_openGLFreezeProtection.get(), QOverload<>::of(&QTimer::start), Qt::QueuedConnection);
|
||||
}
|
||||
break;
|
||||
case OpenGLSafePoint::PostInit:
|
||||
group.deleteEntry(QLatin1String("LastFailureTimestamp"));
|
||||
group.sync();
|
||||
// Deliberately continue with PostFrame
|
||||
Q_FALLTHROUGH();
|
||||
case OpenGLSafePoint::PostFrame:
|
||||
QMetaObject::invokeMethod(m_openGLFreezeProtection.get(), &QTimer::stop, Qt::QueuedConnection);
|
||||
break;
|
||||
case OpenGLSafePoint::PostLastGuardedFrame:
|
||||
m_openGLFreezeProtectionThread->quit();
|
||||
m_openGLFreezeProtectionThread->wait();
|
||||
m_openGLFreezeProtectionThread.reset();
|
||||
m_openGLFreezeProtection.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#include "moc_compositor_x11.cpp"
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de>
|
||||
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class X11SyncManager;
|
||||
class X11Window;
|
||||
|
||||
class KWIN_EXPORT X11Compositor final : public Compositor
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum SuspendReason {
|
||||
NoReasonSuspend = 0,
|
||||
UserSuspend = 1 << 0,
|
||||
BlockRuleSuspend = 1 << 1,
|
||||
ScriptSuspend = 1 << 2,
|
||||
AllReasonSuspend = 0xff
|
||||
};
|
||||
Q_DECLARE_FLAGS(SuspendReasons, SuspendReason)
|
||||
Q_ENUM(SuspendReason)
|
||||
Q_FLAG(SuspendReasons)
|
||||
|
||||
static X11Compositor *create(QObject *parent = nullptr);
|
||||
~X11Compositor() override;
|
||||
|
||||
X11SyncManager *syncManager() const;
|
||||
|
||||
/**
|
||||
* @brief Suspends the Compositor if it is currently active.
|
||||
*
|
||||
* Note: it is possible that the Compositor is not able to suspend. Use isActive to check
|
||||
* whether the Compositor has been suspended.
|
||||
*
|
||||
* @return void
|
||||
* @see resume
|
||||
* @see isActive
|
||||
*/
|
||||
void suspend(SuspendReason reason);
|
||||
|
||||
/**
|
||||
* @brief Resumes the Compositor if it is currently suspended.
|
||||
*
|
||||
* Note: it is possible that the Compositor cannot be resumed, that is there might be Clients
|
||||
* blocking the usage of Compositing or the Scene might be broken. Use isActive to check
|
||||
* whether the Compositor has been resumed. Also check isCompositingPossible and
|
||||
* isOpenGLBroken.
|
||||
*
|
||||
* Note: The starting of the Compositor can require some time and is partially done threaded.
|
||||
* After this method returns the setup may not have been completed.
|
||||
*
|
||||
* @return void
|
||||
* @see suspend
|
||||
* @see isActive
|
||||
* @see isCompositingPossible
|
||||
* @see isOpenGLBroken
|
||||
*/
|
||||
void resume(SuspendReason reason);
|
||||
|
||||
void toggleCompositing() override;
|
||||
void reinitialize() override;
|
||||
void configChanged() override;
|
||||
bool compositingPossible() const override;
|
||||
QString compositingNotPossibleReason() const override;
|
||||
bool openGLCompositingIsBroken() const override;
|
||||
void createOpenGLSafePoint(OpenGLSafePoint safePoint) override;
|
||||
|
||||
/**
|
||||
* Checks whether @p w is the Scene's overlay window.
|
||||
*/
|
||||
bool checkForOverlayWindow(WId w) const;
|
||||
|
||||
/**
|
||||
* @returns Whether the Scene's Overlay X Window is visible.
|
||||
*/
|
||||
bool isOverlayWindowVisible() const;
|
||||
|
||||
void updateClientCompositeBlocking(X11Window *client = nullptr);
|
||||
|
||||
static X11Compositor *self();
|
||||
|
||||
protected:
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void composite(RenderLoop *renderLoop) override;
|
||||
|
||||
private:
|
||||
explicit X11Compositor(QObject *parent);
|
||||
|
||||
std::unique_ptr<QThread> m_openGLFreezeProtectionThread;
|
||||
std::unique_ptr<QTimer> m_openGLFreezeProtection;
|
||||
std::unique_ptr<X11SyncManager> m_syncManager;
|
||||
/**
|
||||
* Whether the Compositor is currently suspended, 8 bits encoding the reason
|
||||
*/
|
||||
SuspendReasons m_suspended;
|
||||
int m_framesToTestForSafety = 3;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
Loading…
Reference in New Issue