From 632127d7f1d86cba4dd17361f24f9fd70a0ae44c Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 5 Jul 2024 16:13:40 +0100 Subject: [PATCH] Client: Improve thread safety determining window size on the render thread updateSurface is called from both the render and GUI thread. We therefore need every property referenced to be thread safe. Rather than guarding each property we cache the buffer size whenever the window geometry or scale changes and put a mutex round this one variable. Change-Id: I4168ced27556e0e4558bbdbd1daa275d7523c33d Reviewed-by: Vlad Zahorodnii (cherry picked from commit 83da29c62f8fb918df8d91826d16b5d5ceb2c704) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit f817608c7152487f489d0f3a227c1d0ceb7b0c2c) Reviewed-by: David Edmundson --- .../client/wayland-egl/qwaylandeglwindow.cpp | 20 +++++++++++++++---- .../client/wayland-egl/qwaylandeglwindow_p.h | 6 ++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp index 652a65630..44f1038c3 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp @@ -50,6 +50,15 @@ QWaylandWindow::WindowType QWaylandEglWindow::windowType() const void QWaylandEglWindow::ensureSize() { + // this is always called on the main thread + QMargins margins = mWindowDecoration ? frameMargins() : QMargins{}; + QRect rect = geometry(); + QSize sizeWithMargins = (rect.size() + QSize(margins.left() + margins.right(), margins.top() + margins.bottom())) * scale(); + { + QWriteLocker lock(&m_bufferSizeLock); + m_bufferSize = sizeWithMargins; + } + updateSurface(false); } @@ -60,14 +69,17 @@ void QWaylandEglWindow::setGeometry(const QRect &rect) // we're now getting a resize we don't want to create it again. // Just resize the wl_egl_window, the EGLSurface will be created // the next time makeCurrent is called. - updateSurface(false); + ensureSize(); } void QWaylandEglWindow::updateSurface(bool create) { - QMargins margins = mWindowDecoration ? frameMargins() : QMargins{}; - QRect rect = geometry(); - QSize sizeWithMargins = (rect.size() + QSize(margins.left() + margins.right(), margins.top() + margins.bottom())) * scale(); + + QSize sizeWithMargins; + { + QReadLocker lock(&m_bufferSizeLock); + sizeWithMargins = m_bufferSize; + } // wl_egl_windows must have both width and height > 0 // mesa's egl returns NULL if we try to create a, invalid wl_egl_window, however not all EGL diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h index 5b9aa9874..048f0b610 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h @@ -60,7 +60,13 @@ private: mutable QOpenGLFramebufferObject *m_contentFBO = nullptr; QSurfaceFormat m_format; + // Size used in the last call to wl_egl_window_resize QSize m_requestedSize; + + // Size of the buffer used by QWaylandWindow + // This is always written to from the main thread, potentially read from the rendering thread + QReadWriteLock m_bufferSizeLock; + QSize m_bufferSize; }; } -- GitLab