wayland: Bump default max buffer size to 1 MiB

This is to prevent disconnecting clients that sometimes struggle with
keeping up with the events that the compositor sends. 1 MiB was eyeballed.

Wayland's wire protocol consists of a stream of messages. Every message
consists of a header (2 words: 1 word for object id, the other word
specifies the message size + event/request opcode) and the arguments.

Considering the compositor sending motion events generated by a mouse
with 1000Hz polling rate, we have

- wl_pointer.motion event size: (4 bytes for serial + 4 bytes for x +
  4 bytes for y + 8 bytes for header) = 20 bytes
- wl_pointer.frame event size: 8 bytes for header

So in total, if the client freezes for a second, the client buffer size
should be at least (20 + 8) * 1000 / 1024 = 27 KiB. 1 MiB corresponds to
the client not processing the motion events for approximately 30 seconds.
This commit is contained in:
Vlad Zahorodnii 2024-04-12 14:58:15 +03:00
parent 5a0ecdba33
commit 7590c6d386
5 changed files with 36 additions and 0 deletions

View file

@ -196,6 +196,11 @@ set_package_properties(Wayland PROPERTIES
TYPE REQUIRED
PURPOSE "Required for building KWin with Wayland support"
)
if (Wayland_VERSION VERSION_GREATER_EQUAL 1.23)
set(HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE 1)
else()
set(HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE 0)
endif()
find_package(WaylandProtocols 1.34)
set_package_properties(WaylandProtocols PROPERTIES

View file

@ -31,3 +31,4 @@ constexpr QLatin1String BREEZE_KDECORATION_PLUGIN_ID("${BREEZE_KDECORATION_PLUGI
#cmakedefine01 HAVE_XWAYLAND_ENABLE_EI_PORTAL
#cmakedefine01 HAVE_GLX
#cmakedefine01 HAVE_DL_LIBRARY
#cmakedefine01 HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE

View file

@ -5,6 +5,9 @@
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "display.h"
#include "config-kwin.h"
#include "clientconnection.h"
#include "display_p.h"
#include "linuxdmabufv1clientbuffer_p.h"
@ -243,6 +246,13 @@ GraphicsBuffer *Display::bufferForResource(wl_resource *resource)
}
}
void Display::setDefaultMaxBufferSize(size_t max)
{
#if HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE
wl_display_set_default_max_buffer_size(d->display, max);
#endif
}
SecurityContext::SecurityContext(Display *display, FileDescriptor &&listenFd, FileDescriptor &&closeFd, const QString &appId)
: QObject(display)
, m_display(display)

View file

@ -116,6 +116,12 @@ public:
*/
static GraphicsBuffer *bufferForResource(wl_resource *resource);
/**
* Sets the default maximum size for connection buffers of new clients. The size is in bytes.
* The minimum buffer size is 4096.
*/
void setDefaultMaxBufferSize(size_t max);
private Q_SLOTS:
void flush();

View file

@ -188,10 +188,24 @@ public:
}
};
static size_t mibToBytes(size_t mib)
{
return mib * (size_t(1) << 20);
}
static size_t defaultMaxBufferSize()
{
if (int hint = qEnvironmentVariableIntValue("KWIN_WAYLAND_DEFAULT_MAX_CONNECTION_BUFFER_SIZE"); hint > 0) {
return hint;
}
return mibToBytes(1);
}
WaylandServer::WaylandServer(QObject *parent)
: QObject(parent)
, m_display(new KWinDisplay(this))
{
m_display->setDefaultMaxBufferSize(defaultMaxBufferSize());
}
WaylandServer::~WaylandServer()