Blame SOURCES/qtwayland-fix-100ms-freeze-when-apps-dont-swap-after-deliverupdaterequest.patch

e455a7
From 9f5b96225885f927727a57b6123d8550d6c373bb Mon Sep 17 00:00:00 2001
e455a7
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
e455a7
Date: Tue, 15 Oct 2019 09:51:43 +0200
e455a7
Subject: [PATCH] Client: Fix 100ms freeze when applications do not swap after deliverUpdateRequest
e455a7
e455a7
[ChangeLog][QPA plugin] Fixed a 100 ms freeze that would occur if applications
e455a7
did not draw after receiving a deliverUpdateRequest().
e455a7
e455a7
QtQuick does this at the start of animations. This should get rid of those
e455a7
backingstore warnings (and also remove a 100ms freeze before animations start
e455a7
in those instances).
e455a7
e455a7
Fixes: QTBUG-76813
e455a7
Change-Id: Id366bf4a14f402fa44530ae46e7b66d9988c14f6
e455a7
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
e455a7
Reviewed-by: John Brooks <john.brooks@qt.io>
e455a7
---
e455a7
e455a7
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
e455a7
index ae26ba0..8d34afd 100644
e455a7
--- a/src/client/qwaylandwindow.cpp
e455a7
+++ b/src/client/qwaylandwindow.cpp
e455a7
@@ -1105,25 +1105,6 @@
e455a7
 
e455a7
 void QWaylandWindow::timerEvent(QTimerEvent *event)
e455a7
 {
e455a7
-    if (event->timerId() == mFallbackUpdateTimerId) {
e455a7
-        killTimer(mFallbackUpdateTimerId);
e455a7
-        mFallbackUpdateTimerId = -1;
e455a7
-        qCDebug(lcWaylandBackingstore) << "mFallbackUpdateTimer timed out";
e455a7
-
e455a7
-        if (!isExposed()) {
e455a7
-            qCDebug(lcWaylandBackingstore) << "Fallback update timer: Window not exposed,"
e455a7
-                                           << "not delivering update request.";
e455a7
-            return;
e455a7
-        }
e455a7
-
e455a7
-        if (mWaitingForUpdate && hasPendingUpdateRequest() && !mWaitingForFrameCallback) {
e455a7
-            qCWarning(lcWaylandBackingstore) << "Delivering update request through fallback timer,"
e455a7
-                                             << "may not be in sync with display";
e455a7
-            deliverUpdateRequest();
e455a7
-        }
e455a7
-    }
e455a7
-
e455a7
-
e455a7
     if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
e455a7
         killTimer(event->timerId());
e455a7
         qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
e455a7
@@ -1135,6 +1116,7 @@
e455a7
 
e455a7
 void QWaylandWindow::requestUpdate()
e455a7
 {
e455a7
+    qCDebug(lcWaylandBackingstore) << "requestUpdate";
e455a7
     Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
e455a7
 
e455a7
     // If we have a frame callback all is good and will be taken care of there
e455a7
@@ -1142,20 +1124,17 @@
e455a7
         return;
e455a7
 
e455a7
     // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
e455a7
-    if (mWaitingForUpdate) {
e455a7
-        // Ideally, we should just have returned here, but we're not guaranteed that the client
e455a7
-        // will actually update, so start this timer to deliver another request update after a while
e455a7
-        // *IF* the client doesn't update.
e455a7
-        int fallbackTimeout = 100;
e455a7
-        mFallbackUpdateTimerId = startTimer(fallbackTimeout);
e455a7
-        return;
e455a7
-    }
e455a7
+    // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
e455a7
+    // here so we can get this information when debugging update/frame callback issues.
e455a7
+    // Continue as nothing happened, though.
e455a7
+    if (mWaitingForUpdate)
e455a7
+        qCDebug(lcWaylandBackingstore) << "requestUpdate called twice without committing anything";
e455a7
 
e455a7
     // Some applications (such as Qt Quick) depend on updates being delivered asynchronously,
e455a7
     // so use invokeMethod to delay the delivery a bit.
e455a7
     QMetaObject::invokeMethod(this, [this] {
e455a7
         // Things might have changed in the meantime
e455a7
-        if (hasPendingUpdateRequest() && !mWaitingForUpdate && !mWaitingForFrameCallback)
e455a7
+        if (hasPendingUpdateRequest() && !mWaitingForFrameCallback)
e455a7
             deliverUpdateRequest();
e455a7
     }, Qt::QueuedConnection);
e455a7
 }
e455a7
@@ -1165,6 +1144,7 @@
e455a7
 // Can be called from the render thread (without locking anything) so make sure to not make races in this method.
e455a7
 void QWaylandWindow::handleUpdate()
e455a7
 {
e455a7
+    qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
e455a7
     // TODO: Should sync subsurfaces avoid requesting frame callbacks?
e455a7
     QReadLocker lock(&mSurfaceLock);
e455a7
     if (!isInitialized())
e455a7
@@ -1175,15 +1155,6 @@
e455a7
         mFrameCallback = nullptr;
e455a7
     }
e455a7
 
e455a7
-    if (mFallbackUpdateTimerId != -1) {
e455a7
-        // Ideally, we would stop the fallback timer here, but since we're on another thread,
e455a7
-        // it's not allowed. Instead we set mFallbackUpdateTimer to -1 here, so we'll just
e455a7
-        // ignore it if it times out before it's cleaned up by the invokeMethod call.
e455a7
-        int id = mFallbackUpdateTimerId;
e455a7
-        mFallbackUpdateTimerId = -1;
e455a7
-        QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection);
e455a7
-    }
e455a7
-
e455a7
     mFrameCallback = frame();
e455a7
     wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
e455a7
     mWaitingForFrameCallback = true;
e455a7
@@ -1203,6 +1174,7 @@
e455a7
 
e455a7
 void QWaylandWindow::deliverUpdateRequest()
e455a7
 {
e455a7
+    qCDebug(lcWaylandBackingstore) << "deliverUpdateRequest";
e455a7
     mWaitingForUpdate = true;
e455a7
     QPlatformWindow::deliverUpdateRequest();
e455a7
 }
e455a7
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
e455a7
index b03d92e..e4a1124 100644
e455a7
--- a/src/client/qwaylandwindow_p.h
e455a7
+++ b/src/client/qwaylandwindow_p.h
e455a7
@@ -232,7 +232,6 @@
e455a7
 
e455a7
     // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
e455a7
     bool mWaitingForUpdate = false;
e455a7
-    int mFallbackUpdateTimerId = -1; // Started when waiting for app to commit
e455a7
 
e455a7
     QMutex mResizeLock;
e455a7
     bool mWaitingToApplyConfigure = false;