Merge remote-tracking branch 'origin/5.12' into 5.13

Conflicts:
	.qmake.conf

Change-Id: I436405677453e7df43258363c0d5c88d7b3790d0
This commit is contained in:
Qt Forward Merge Bot 2019-07-09 03:06:39 +02:00 committed by Edward Welbourne
commit a5801f3f36
2 changed files with 42 additions and 32 deletions

View File

@ -245,6 +245,13 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
mFrameCallback = nullptr;
}
int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
if (timerId != -1) {
killTimer(timerId);
}
mWaitingForFrameCallback = false;
mFrameCallbackTimedOut = false;
mMask = QRegion();
mQueuedBuffer = nullptr;
}
@ -614,29 +621,34 @@ const wl_callback_listener QWaylandWindow::callbackListener = {
Q_UNUSED(callback);
Q_UNUSED(time);
auto *window = static_cast<QWaylandWindow*>(data);
if (window->thread() != QThread::currentThread())
QMetaObject::invokeMethod(window, [=] { window->handleFrameCallback(); }, Qt::QueuedConnection);
else
window->handleFrameCallback();
window->handleFrameCallback();
}
};
void QWaylandWindow::handleFrameCallback()
{
bool wasExposed = isExposed();
if (mFrameCallbackTimerId != -1) {
killTimer(mFrameCallbackTimerId);
mFrameCallbackTimerId = -1;
}
// Stop the timer and stop waiting immediately
int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
mWaitingForFrameCallback = false;
mFrameCallbackTimedOut = false;
if (!wasExposed && isExposed())
sendExposeEvent(QRect(QPoint(), geometry().size()));
if (wasExposed && hasPendingUpdateRequest())
deliverUpdateRequest();
// The rest can wait until we can run it on the correct thread
auto doHandleExpose = [this, timerId]() {
if (timerId != -1)
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;
@ -658,11 +670,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
if (mFrameCallbackTimerId != -1) {
int id = mFrameCallbackTimerId;
mFrameCallbackTimerId = -1;
QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
}
// Ordered semantics is needed to avoid stopping the timer twice and not miss it when it's
// started by other writes
int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
if (fcbId != -1)
QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
return !mWaitingForFrameCallback;
}
@ -1100,9 +1112,9 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
}
}
if (event->timerId() == mFrameCallbackTimerId) {
killTimer(mFrameCallbackTimerId);
mFrameCallbackTimerId = -1;
if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
killTimer(event->timerId());
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
mFrameCallbackTimedOut = true;
mWaitingForUpdate = false;
@ -1155,7 +1167,7 @@ void QWaylandWindow::handleUpdate()
// ignore it if it times out before it's cleaned up by the invokeMethod call.
int id = mFallbackUpdateTimerId;
mFallbackUpdateTimerId = -1;
QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection);
}
mFrameCallback = frame();
@ -1164,14 +1176,12 @@ void QWaylandWindow::handleUpdate()
mWaitingForUpdate = false;
// Stop current frame timer if any, can't use killTimer directly, see comment above.
if (mFrameCallbackTimerId != -1) {
int id = mFrameCallbackTimerId;
mFrameCallbackTimerId = -1;
QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
}
int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
if (fcbId != -1)
QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
// 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)
mFrameCallbackTimerId = startTimer(100);
}, Qt::QueuedConnection);

View File

@ -222,7 +222,7 @@ protected:
WId mWindowId;
bool mWaitingForFrameCallback = false;
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_event_queue *mFrameQueue = nullptr;
QWaitCondition mFrameSyncWait;