wayland: implement tearing_control_v1

master
Xaver Hugl 2 years ago
parent 1a97d384f1
commit b261050be1

@ -205,7 +205,7 @@ find_package(Wayland 1.21 REQUIRED COMPONENTS
Server
)
find_package(WaylandProtocols 1.27)
find_package(WaylandProtocols 1.30)
set_package_properties(WaylandProtocols PROPERTIES
TYPE REQUIRED
PURPOSE "Collection of Wayland protocols that add functionality not available in the Wayland core protocol"

@ -184,6 +184,10 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml
PROTOCOL ${WaylandProtocols_DATADIR}/staging/ext-idle-notify/ext-idle-notify-v1.xml
BASENAME ext-idle-notify-v1
)
ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml
PROTOCOL ${WaylandProtocols_DATADIR}/staging/tearing-control/tearing-control-v1.xml
BASENAME tearing-control-v1
)
ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml
PROTOCOL ${WaylandProtocols_DATADIR}/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.xml
@ -256,6 +260,7 @@ target_sources(kwin PRIVATE
surface_interface.cpp
surfacerole.cpp
tablet_v2_interface.cpp
tearingcontrol_v1_interface.cpp
textinput.cpp
textinput_v2_interface.cpp
textinput_v3_interface.cpp

@ -536,6 +536,10 @@ void SurfaceState::mergeInto(SurfaceState *target)
target->contentType = contentType;
target->contentTypeIsSet = true;
}
if (tearingIsSet) {
target->presentationHint = presentationHint;
target->tearingIsSet = true;
}
*this = SurfaceState{};
below = target->below;
@ -1097,4 +1101,9 @@ QPointF SurfaceInterface::toSurfaceLocal(const QPointF &point) const
return QPointF(point.x() * d->scaleOverride, point.y() * d->scaleOverride);
}
PresentationHint SurfaceInterface::presentationHint() const
{
return d->current.presentationHint;
}
} // namespace KWaylandServer

@ -28,6 +28,11 @@ class SubSurfaceInterface;
class SurfaceInterfacePrivate;
class LinuxDmaBufV1Feedback;
enum class PresentationHint {
VSync,
Async
};
/**
* @brief Resource representing a wl_surface.
*
@ -336,6 +341,11 @@ public:
*/
QPointF toSurfaceLocal(const QPointF &point) const;
/**
* @returns if the client thinks the content of this surface is suitable for presentation with tearing
*/
PresentationHint presentationHint() const;
Q_SIGNALS:
/**
* This signal is emitted when the underlying wl_surface resource is about to be freed.

@ -20,6 +20,7 @@ class IdleInhibitorV1Interface;
class SurfaceRole;
class ViewportInterface;
class ContentTypeV1Interface;
class TearingControlV1Interface;
struct SurfaceState
{
@ -40,6 +41,7 @@ struct SurfaceState
bool bufferScaleIsSet = false;
bool bufferTransformIsSet = false;
bool contentTypeIsSet = false;
bool tearingIsSet = false;
qint32 bufferScale = 1;
KWin::Output::Transform bufferTransform = KWin::Output::Transform::Normal;
wl_list frameCallbacks;
@ -50,6 +52,7 @@ struct SurfaceState
QPointer<ContrastInterface> contrast;
QPointer<SlideInterface> slide;
KWin::ContentType contentType = KWin::ContentType::None;
PresentationHint presentationHint = PresentationHint::VSync;
// Subsurfaces are stored in two lists. The below list contains subsurfaces that
// are below their parent surface; the above list contains subsurfaces that are
@ -139,6 +142,7 @@ public:
std::unique_ptr<LinuxDmaBufV1Feedback> dmabufFeedbackV1;
QPointer<ContentTypeV1Interface> contentTypeInterface;
ClientConnection *client = nullptr;
TearingControlV1Interface *tearing = nullptr;
protected:
void surface_destroy_resource(Resource *resource) override;

@ -0,0 +1,104 @@
/*
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "tearingcontrol_v1_interface.h"
#include "display.h"
#include "surface_interface_p.h"
namespace KWaylandServer
{
static constexpr uint32_t s_version = 1;
class TearingControlManagerV1InterfacePrivate : public QtWaylandServer::wp_tearing_control_manager_v1
{
public:
TearingControlManagerV1InterfacePrivate(Display *display);
private:
void wp_tearing_control_manager_v1_destroy(Resource *resource) override;
void wp_tearing_control_manager_v1_get_tearing_control(Resource *resource, uint32_t id, struct ::wl_resource *surface) override;
};
class TearingControlV1Interface : private QtWaylandServer::wp_tearing_control_v1
{
public:
TearingControlV1Interface(SurfaceInterface *surface, wl_client *client, uint32_t id);
~TearingControlV1Interface();
private:
void wp_tearing_control_v1_set_presentation_hint(Resource *resource, uint32_t hint) override;
void wp_tearing_control_v1_destroy(Resource *resource) override;
void wp_tearing_control_v1_destroy_resource(Resource *resource) override;
const QPointer<SurfaceInterface> m_surface;
};
TearingControlManagerV1Interface::TearingControlManagerV1Interface(Display *display, QObject *parent)
: QObject(parent)
{
}
TearingControlManagerV1Interface::~TearingControlManagerV1Interface() = default;
TearingControlManagerV1InterfacePrivate::TearingControlManagerV1InterfacePrivate(Display *display)
: QtWaylandServer::wp_tearing_control_manager_v1(*display, s_version)
{
}
void TearingControlManagerV1InterfacePrivate::wp_tearing_control_manager_v1_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void TearingControlManagerV1InterfacePrivate::wp_tearing_control_manager_v1_get_tearing_control(Resource *resource, uint32_t id, struct ::wl_resource *wlSurface)
{
SurfaceInterface *surface = SurfaceInterface::get(wlSurface);
if (SurfaceInterfacePrivate::get(surface)->tearing) {
wl_resource_post_error(resource->handle, QtWaylandServer::wp_tearing_control_manager_v1::error_tearing_control_exists, "Surface already has a wp_surface_tearing_control_v1");
return;
}
SurfaceInterfacePrivate::get(surface)->tearing = new TearingControlV1Interface(surface, resource->client(), id);
}
TearingControlV1Interface::TearingControlV1Interface(SurfaceInterface *surface, wl_client *client, uint32_t id)
: QtWaylandServer::wp_tearing_control_v1(client, id, s_version)
, m_surface(surface)
{
}
TearingControlV1Interface::~TearingControlV1Interface()
{
if (m_surface) {
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(m_surface);
surfacePrivate->pending.presentationHint = PresentationHint::VSync;
surfacePrivate->pending.tearingIsSet = true;
surfacePrivate->tearing = nullptr;
}
}
void TearingControlV1Interface::wp_tearing_control_v1_set_presentation_hint(Resource *resource, uint32_t hint)
{
if (m_surface) {
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(m_surface);
if (hint == presentation_hint::presentation_hint_async) {
surfacePrivate->pending.presentationHint = PresentationHint::Async;
} else {
surfacePrivate->pending.presentationHint = PresentationHint::VSync;
}
surfacePrivate->pending.tearingIsSet = true;
}
}
void TearingControlV1Interface::wp_tearing_control_v1_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void TearingControlV1Interface::wp_tearing_control_v1_destroy_resource(Resource *resource)
{
delete this;
}
}

@ -0,0 +1,31 @@
/*
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include "surface_interface.h"
#include "qwayland-server-tearing-control-v1.h"
#include <QObject>
namespace KWaylandServer
{
class TearingControlManagerV1InterfacePrivate;
class TearingControlV1Interface;
class Display;
class TearingControlManagerV1Interface : public QObject
{
Q_OBJECT
public:
TearingControlManagerV1Interface(Display *display, QObject *parent = nullptr);
~TearingControlManagerV1Interface() override;
private:
std::unique_ptr<TearingControlManagerV1InterfacePrivate> d;
};
}

@ -59,6 +59,7 @@
#include "wayland/shadow_interface.h"
#include "wayland/subcompositor_interface.h"
#include "wayland/tablet_v2_interface.h"
#include "wayland/tearingcontrol_v1_interface.h"
#include "wayland/viewporter_interface.h"
#include "wayland/xdgactivation_v1_interface.h"
#include "wayland/xdgdecoration_v1_interface.h"
@ -487,6 +488,7 @@ bool WaylandServer::init(InitializationFlags flags)
});
m_contentTypeManager = new KWaylandServer::ContentTypeManagerV1Interface(m_display, m_display);
m_tearingControlInterface = new KWaylandServer::TearingControlManagerV1Interface(m_display, m_display);
return true;
}

@ -51,6 +51,7 @@ class XdgDecorationManagerV1Interface;
class XWaylandKeyboardGrabManagerV1Interface;
class ContentTypeManagerV1Interface;
class DrmLeaseManagerV1;
class TearingControlManagerV1Interface;
}
namespace KWin
@ -290,6 +291,7 @@ private:
XdgActivationV1Integration *m_xdgActivationIntegration = nullptr;
KWaylandServer::XWaylandKeyboardGrabManagerV1Interface *m_xWaylandKeyboardGrabManager = nullptr;
KWaylandServer::ContentTypeManagerV1Interface *m_contentTypeManager = nullptr;
KWaylandServer::TearingControlManagerV1Interface *m_tearingControlInterface = nullptr;
QList<Window *> m_windows;
InitializationFlags m_initFlags;
QHash<Output *, KWaylandServer::OutputInterface *> m_waylandOutputs;

Loading…
Cancel
Save