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

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