Merge "Merge remote-tracking branch 'origin/5.13' into dev"

This commit is contained in:
Qt Forward Merge Bot 2019-07-16 03:00:13 +02:00
commit d3ea4c8456
2 changed files with 42 additions and 32 deletions

View File

@ -249,6 +249,13 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
mFrameCallback = nullptr; mFrameCallback = nullptr;
} }
int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
if (timerId != -1) {
killTimer(timerId);
}
mWaitingForFrameCallback = false;
mFrameCallbackTimedOut = false;
mMask = QRegion(); mMask = QRegion();
mQueuedBuffer = nullptr; mQueuedBuffer = nullptr;
} }
@ -573,29 +580,34 @@ const wl_callback_listener QWaylandWindow::callbackListener = {
Q_UNUSED(callback); Q_UNUSED(callback);
Q_UNUSED(time); Q_UNUSED(time);
auto *window = static_cast<QWaylandWindow*>(data); auto *window = static_cast<QWaylandWindow*>(data);
if (window->thread() != QThread::currentThread()) window->handleFrameCallback();
QMetaObject::invokeMethod(window, [=] { window->handleFrameCallback(); }, Qt::QueuedConnection);
else
window->handleFrameCallback();
} }
}; };
void QWaylandWindow::handleFrameCallback() void QWaylandWindow::handleFrameCallback()
{ {
bool wasExposed = isExposed(); // Stop the timer and stop waiting immediately
int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
if (mFrameCallbackTimerId != -1) {
killTimer(mFrameCallbackTimerId);
mFrameCallbackTimerId = -1;
}
mWaitingForFrameCallback = false; mWaitingForFrameCallback = false;
mFrameCallbackTimedOut = false;
if (!wasExposed && isExposed()) // The rest can wait until we can run it on the correct thread
sendExposeEvent(QRect(QPoint(), geometry().size())); auto doHandleExpose = [this, timerId]() {
if (wasExposed && hasPendingUpdateRequest()) if (timerId != -1)
deliverUpdateRequest(); killTimer(timerId);
bool wasExposed = isExposed();
mFrameCallbackTimedOut = false;
if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
sendExposeEvent(QRect(QPoint(), geometry().size()));
if (wasExposed && hasPendingUpdateRequest())
deliverUpdateRequest();
};
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, doHandleExpose);
} else {
doHandleExpose();
}
} }
QMutex QWaylandWindow::mFrameSyncMutex; QMutex QWaylandWindow::mFrameSyncMutex;
@ -617,11 +629,11 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
} }
// Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread // Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread
if (mFrameCallbackTimerId != -1) { // Ordered semantics is needed to avoid stopping the timer twice and not miss it when it's
int id = mFrameCallbackTimerId; // started by other writes
mFrameCallbackTimerId = -1; int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); if (fcbId != -1)
} QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
return !mWaitingForFrameCallback; return !mWaitingForFrameCallback;
} }
@ -1077,9 +1089,9 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
} }
} }
if (event->timerId() == mFrameCallbackTimerId) {
killTimer(mFrameCallbackTimerId); if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
mFrameCallbackTimerId = -1; killTimer(event->timerId());
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed"; qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
mFrameCallbackTimedOut = true; mFrameCallbackTimedOut = true;
mWaitingForUpdate = false; mWaitingForUpdate = false;
@ -1132,7 +1144,7 @@ void QWaylandWindow::handleUpdate()
// ignore it if it times out before it's cleaned up by the invokeMethod call. // ignore it if it times out before it's cleaned up by the invokeMethod call.
int id = mFallbackUpdateTimerId; int id = mFallbackUpdateTimerId;
mFallbackUpdateTimerId = -1; mFallbackUpdateTimerId = -1;
QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection);
} }
mFrameCallback = mSurface->frame(); mFrameCallback = mSurface->frame();
@ -1141,14 +1153,12 @@ void QWaylandWindow::handleUpdate()
mWaitingForUpdate = false; mWaitingForUpdate = false;
// Stop current frame timer if any, can't use killTimer directly, see comment above. // Stop current frame timer if any, can't use killTimer directly, see comment above.
if (mFrameCallbackTimerId != -1) { int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
int id = mFrameCallbackTimerId; if (fcbId != -1)
mFrameCallbackTimerId = -1; QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
}
// Start a timer for handling the case when the compositor stops sending frame callbacks. // Start a timer for handling the case when the compositor stops sending frame callbacks.
QMetaObject::invokeMethod(this, [=] { // Again; can't do it directly QMetaObject::invokeMethod(this, [this] { // Again; can't do it directly
if (mWaitingForFrameCallback) if (mWaitingForFrameCallback)
mFrameCallbackTimerId = startTimer(100); mFrameCallbackTimerId = startTimer(100);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -219,7 +219,7 @@ protected:
WId mWindowId; WId mWindowId;
bool mWaitingForFrameCallback = false; bool mWaitingForFrameCallback = false;
bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
int mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback QAtomicInt mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
struct ::wl_callback *mFrameCallback = nullptr; struct ::wl_callback *mFrameCallback = nullptr;
struct ::wl_event_queue *mFrameQueue = nullptr; struct ::wl_event_queue *mFrameQueue = nullptr;
QWaitCondition mFrameSyncWait; QWaitCondition mFrameSyncWait;