From d825f60c2402c747df70fadfd2cff879880302a6037db54797b8bd08fa82e82d Mon Sep 17 00:00:00 2001 From: Christophe Giboudeaux Date: Fri, 4 Feb 2022 11:49:31 +0000 Subject: [PATCH] Accepting request 951555 from home:Vogtinator:qt5.15 - Add patches to fix applications not updating after some time (kde#449163): * 0001-Client-Remove-mWaitingForUpdateDelivery.patch * 0002-Guard-mResizeDirty-by-the-correctMutex.patch * 0003-Fix-up-mutexes-for-frame-callbacks.patch - Add patch to fix several feature detection tests: * 0001-Use-proper-dependencies-in-compile-tests.patch OBS-URL: https://build.opensuse.org/request/show/951555 OBS-URL: https://build.opensuse.org/package/show/KDE:Qt:5.15/libqt5-qtwayland?expand=0&rev=20 --- ...ent-Remove-mWaitingForUpdateDelivery.patch | 77 +++++++++++ ...proper-dependencies-in-compile-tests.patch | 120 ++++++++++++++++++ ...ard-mResizeDirty-by-the-correctMutex.patch | 37 ++++++ 0003-Fix-up-mutexes-for-frame-callbacks.patch | 87 +++++++++++++ libqt5-qtwayland.changes | 10 ++ libqt5-qtwayland.spec | 8 ++ 6 files changed, 339 insertions(+) create mode 100644 0001-Client-Remove-mWaitingForUpdateDelivery.patch create mode 100644 0001-Use-proper-dependencies-in-compile-tests.patch create mode 100644 0002-Guard-mResizeDirty-by-the-correctMutex.patch create mode 100644 0003-Fix-up-mutexes-for-frame-callbacks.patch diff --git a/0001-Client-Remove-mWaitingForUpdateDelivery.patch b/0001-Client-Remove-mWaitingForUpdateDelivery.patch new file mode 100644 index 0000000..b2a9d36 --- /dev/null +++ b/0001-Client-Remove-mWaitingForUpdateDelivery.patch @@ -0,0 +1,77 @@ +From 78b517296568e4cd960ef4e13001d1200ad33e01 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Tue, 1 Feb 2022 13:05:36 +0200 +Subject: [PATCH 1/3] Client: Remove mWaitingForUpdateDelivery + +Currently, mWaitingForUpdateDelivery is shared between the main thread +(doHandleFrameCallback()) and the frame callback event thread +(handleFrameCallback()), however the access to it is not synchronized +between neither both threads. On the other hand, QWaylandWindow +already ensures not to create a frame callback if there's already one +pending. + +This change removes mWaitingForUpdateDelivery flag because it should be +already covered by mWaitingForFrameCallback and to remove unsynchronized +shared state between threads. + +Change-Id: I0e5a25d18d1e66c4d7683e7e972330c4d7cbbf38 +--- + src/client/qwaylandwindow.cpp | 29 ++++++++++++----------------- + src/client/qwaylandwindow_p.h | 1 - + 2 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index acfe390e..30ae5345 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -638,23 +638,18 @@ void QWaylandWindow::handleFrameCallback() + mFrameCallbackElapsedTimer.invalidate(); + + // The rest can wait until we can run it on the correct thread +- if (!mWaitingForUpdateDelivery) { +- auto doHandleExpose = [this]() { +- bool wasExposed = isExposed(); +- mFrameCallbackTimedOut = false; +- if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed? +- sendExposeEvent(QRect(QPoint(), geometry().size())); +- if (wasExposed && hasPendingUpdateRequest()) +- deliverUpdateRequest(); +- +- mWaitingForUpdateDelivery = false; +- }; +- +- // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync() +- // in the single-threaded case. +- mWaitingForUpdateDelivery = true; +- QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection); +- } ++ auto doHandleExpose = [this]() { ++ bool wasExposed = isExposed(); ++ mFrameCallbackTimedOut = false; ++ if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed? ++ sendExposeEvent(QRect(QPoint(), geometry().size())); ++ if (wasExposed && hasPendingUpdateRequest()) ++ deliverUpdateRequest(); ++ }; ++ ++ // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync() ++ // in the single-threaded case. ++ QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection); + + mFrameSyncWait.notify_all(); + } +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h +index d45980a8..3ff68ccb 100644 +--- a/src/client/qwaylandwindow_p.h ++++ b/src/client/qwaylandwindow_p.h +@@ -228,7 +228,6 @@ protected: + WId mWindowId; + bool mWaitingForFrameCallback = false; + bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out +- bool mWaitingForUpdateDelivery = false; + int mFrameCallbackCheckIntervalTimerId = -1; + QElapsedTimer mFrameCallbackElapsedTimer; + struct ::wl_callback *mFrameCallback = nullptr; +-- +2.34.0 + diff --git a/0001-Use-proper-dependencies-in-compile-tests.patch b/0001-Use-proper-dependencies-in-compile-tests.patch new file mode 100644 index 0000000..f98d2e5 --- /dev/null +++ b/0001-Use-proper-dependencies-in-compile-tests.patch @@ -0,0 +1,120 @@ +From 95bdca4b2ff43205f0666a5beda124d8ca326954 Mon Sep 17 00:00:00 2001 +From: Fabian Vogt +Date: Fri, 4 Feb 2022 11:07:36 +0100 +Subject: [PATCH] Use proper dependencies in compile tests + +Use the dependencies as found by the "libraries" section instead of relying +on them being available in the default location (e.g. "-ldrm"). + +Additionally, VK_USE_PLATFORM_WAYLAND_KHR requires , so +add the wayland-client dependency. + +This fixes those tests if e.g. wayland-client headers need to be found through +pkgconfig. +--- + src/client/configure.json | 8 ++++---- + src/compositor/configure.json | 34 +++++++++++++++++++++++++++++----- + 2 files changed, 33 insertions(+), 9 deletions(-) + +diff --git a/src/client/configure.json b/src/client/configure.json +index 2f424580..29222357 100644 +--- a/src/client/configure.json ++++ b/src/client/configure.json +@@ -149,8 +149,7 @@ + "#endif" + ] + }, +- "libs": "-ldrm", +- "use": "egl" ++ "use": "drm egl" + }, + "vulkan-server-buffer": { + "label": "Vulkan Buffer Sharing", +@@ -168,7 +167,8 @@ + "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;", + "return 0;" + ] +- } ++ }, ++ "use": "wayland-client" + }, + "egl_1_5-wayland": { + "label": "EGL 1.5 with Wayland Platform", +@@ -183,7 +183,7 @@ + "eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, (struct wl_display *)(nullptr), nullptr);" + ] + }, +- "use": "egl" ++ "use": "egl wayland-client" + } + }, + +diff --git a/src/compositor/configure.json b/src/compositor/configure.json +index bcfd5215..da95d07b 100644 +--- a/src/compositor/configure.json ++++ b/src/compositor/configure.json +@@ -7,6 +7,31 @@ + "testDir": "../../config.tests", + + "libraries": { ++ "wayland-client": { ++ "label": "Wayland client library", ++ "headers": "wayland-version.h", ++ "test": { ++ "main": [ ++ "#if WAYLAND_VERSION_MAJOR < 1", ++ "# error Wayland 1.8.0 or higher required", ++ "#endif", ++ "#if WAYLAND_VERSION_MAJOR == 1", ++ "# if WAYLAND_VERSION_MINOR < 8", ++ "# error Wayland 1.8.0 or higher required", ++ "# endif", ++ "# if WAYLAND_VERSION_MINOR == 8", ++ "# if WAYLAND_VERSION_MICRO < 0", ++ "# error Wayland 1.8.0 or higher required", ++ "# endif", ++ "# endif", ++ "#endif" ++ ] ++ }, ++ "sources": [ ++ { "type": "pkgConfig", "args": "wayland-client" }, ++ "-lwayland-client" ++ ] ++ }, + "wayland-server": { + "label": "wayland-server", + "headers": "wayland-version.h", +@@ -151,8 +176,7 @@ + "#endif" + ] + }, +- "libs": "-ldrm", +- "use": "egl" ++ "use": "drm egl" + }, + "dmabuf-client-buffer": { + "label": "Linux Client dma-buf Buffer Sharing", +@@ -176,8 +200,7 @@ + "return 0;" + ] + }, +- "libs": "-ldrm", +- "use": "egl" ++ "use": "drm egl" + }, + "vulkan-server-buffer": { + "label": "Vulkan Buffer Sharing", +@@ -195,7 +218,8 @@ + "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;", + "return 0;" + ] +- } ++ }, ++ "use": "wayland-client" + } + }, + +-- +2.34.0 + diff --git a/0002-Guard-mResizeDirty-by-the-correctMutex.patch b/0002-Guard-mResizeDirty-by-the-correctMutex.patch new file mode 100644 index 0000000..6cbe5ed --- /dev/null +++ b/0002-Guard-mResizeDirty-by-the-correctMutex.patch @@ -0,0 +1,37 @@ +From 133b84352063dd959ae0cf21888dd10aa1443b76 Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Thu, 3 Feb 2022 19:42:33 +0000 +Subject: [PATCH 2/3] Guard mResizeDirty by the correctMutex + +mResizeDirty is used in the GUI thread in setCanResize which can be +called from the GUI thread. It is queried and set whilst the resizeLock +is held. We need to guard our usage. + +Change-Id: I5f8dcf8aa2cb2c4bb6274103df1da9e3e268605a +--- + src/client/qwaylandwindow.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index 30ae5345..61700b32 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -357,11 +357,12 @@ void QWaylandWindow::setGeometry(const QRect &rect) + if (mWindowDecoration) + mWindowDecoration->update(); + +- if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize) ++ if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize) { ++ QMutexLocker lock(&mResizeLock); + mResizeDirty = true; +- else ++ } else { + QWindowSystemInterface::handleGeometryChange(window(), geometry()); +- ++ } + mSentInitialResize = true; + } + QRect exposeGeometry(QPoint(), geometry().size()); +-- +2.34.0 + diff --git a/0003-Fix-up-mutexes-for-frame-callbacks.patch b/0003-Fix-up-mutexes-for-frame-callbacks.patch new file mode 100644 index 0000000..a09ba1c --- /dev/null +++ b/0003-Fix-up-mutexes-for-frame-callbacks.patch @@ -0,0 +1,87 @@ +From ee0ab1c58f1020e901b665c79684266730f1ce29 Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Thu, 3 Feb 2022 14:27:08 +0000 +Subject: [PATCH 3/3] Fix up mutexes for frame callbacks + +Everything related to frame callback timings is used by potentially 3 +threads. Access needs guarding. + +Change-Id: I9f22390c175d9f2f63d31b1ebf0cdc0b830be937 +--- + src/client/qwaylandwindow.cpp | 14 +++++++++----- + src/client/qwaylandwindow_p.h | 10 +++++++--- + 2 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index 61700b32..84dcacc3 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -256,8 +256,12 @@ void QWaylandWindow::reset() + mFrameCallback = nullptr; + } + +- mFrameCallbackElapsedTimer.invalidate(); +- mWaitingForFrameCallback = false; ++ { ++ QMutexLocker locker(&mFrameSyncMutex); ++ mFrameCallbackElapsedTimer.invalidate(); ++ mWaitingForFrameCallback = false; ++ } ++ + mFrameCallbackTimedOut = false; + + mMask = QRegion(); +@@ -1132,6 +1136,7 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa + + void QWaylandWindow::timerEvent(QTimerEvent *event) + { ++ QMutexLocker locker(&mFrameSyncMutex); + if (event->timerId() != mFrameCallbackCheckIntervalTimerId) + return; + +@@ -1190,15 +1195,14 @@ void QWaylandWindow::handleUpdate() + { + qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread(); + +- if (mWaitingForFrameCallback) +- return; +- + // TODO: Should sync subsurfaces avoid requesting frame callbacks? + QReadLocker lock(&mSurfaceLock); + if (!mSurface) + return; + + QMutexLocker locker(&mFrameSyncMutex); ++ if (mWaitingForFrameCallback) ++ return; + + struct ::wl_surface *wrappedSurface = reinterpret_cast(wl_proxy_create_wrapper(mSurface->object())); + wl_proxy_set_queue(reinterpret_cast(wrappedSurface), mDisplay->frameEventQueue()); +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h +index 3ff68ccb..025d7917 100644 +--- a/src/client/qwaylandwindow_p.h ++++ b/src/client/qwaylandwindow_p.h +@@ -226,13 +226,17 @@ protected: + Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton; + + WId mWindowId; ++ ++ // The following are used by the main thread the render thread and the event frame thread ++ // Access should be guarded by mFrameSyncMutex ++ QMutex mFrameSyncMutex; ++ QWaitCondition mFrameSyncWait; + bool mWaitingForFrameCallback = false; +- bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out + int mFrameCallbackCheckIntervalTimerId = -1; + QElapsedTimer mFrameCallbackElapsedTimer; ++ ++ bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out + struct ::wl_callback *mFrameCallback = nullptr; +- QMutex mFrameSyncMutex; +- QWaitCondition mFrameSyncWait; + + // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer + bool mWaitingForUpdate = false; +-- +2.34.0 + diff --git a/libqt5-qtwayland.changes b/libqt5-qtwayland.changes index 64fd3aa..4bdc935 100644 --- a/libqt5-qtwayland.changes +++ b/libqt5-qtwayland.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Thu Feb 3 16:51:41 UTC 2022 - Fabian Vogt + +- Add patches to fix applications not updating after some time (kde#449163): + * 0001-Client-Remove-mWaitingForUpdateDelivery.patch + * 0002-Guard-mResizeDirty-by-the-correctMutex.patch + * 0003-Fix-up-mutexes-for-frame-callbacks.patch +- Add patch to fix several feature detection tests: + * 0001-Use-proper-dependencies-in-compile-tests.patch + ------------------------------------------------------------------- Thu Jan 20 16:33:58 UTC 2022 - Fabian Vogt diff --git a/libqt5-qtwayland.spec b/libqt5-qtwayland.spec index dfa4e97..8a7104a 100644 --- a/libqt5-qtwayland.spec +++ b/libqt5-qtwayland.spec @@ -37,6 +37,14 @@ Source: %{tar_version}.tar.xz Source1: baselibs.conf # PATCH-FIX-OPENSUSE Patch1: 0001-Revert-Bump-version.patch +# PATCH-FIX-UPSTREAM https://codereview.qt-project.org/c/qt/qtwayland/+/393273 +Patch2: 0001-Client-Remove-mWaitingForUpdateDelivery.patch +# https://codereview.qt-project.org/c/qt/qtwayland/+/393828/1 +Patch3: 0002-Guard-mResizeDirty-by-the-correctMutex.patch +# https://codereview.qt-project.org/c/qt/qtwayland/+/393826/1 +Patch4: 0003-Fix-up-mutexes-for-frame-callbacks.patch +# To be sent upstream +Patch10: 0001-Use-proper-dependencies-in-compile-tests.patch BuildRequires: fdupes BuildRequires: libqt5-qtbase-private-headers-devel >= %{real_version} BuildRequires: libqt5-qtdeclarative-private-headers-devel >= %{real_version}