summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2023-04-24 16:36:45 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-04-26 17:45:55 +0000
commit6c490b2a2884eaf643f2940c521f6b992e9d5283 (patch)
treee9190f08a7cb6f1bc1e4441e9b33ce5348037120
parent955377a6c33f5409c5d18cd50fdfab085424c4d7 (diff)
downloadqtbase-6c490b2a2884eaf643f2940c521f6b992e9d5283.tar.gz
macOS: Handle failure to create display link or invalid display link
In some rare situations the display link may fail to create, or will be created in an uninitialized state: https://bugzilla.mozilla.org/show_bug.cgi?id=1201401#c123 When the latter happens the display link thread will crash in CVCGDisplayLink::getDisplayTimes(). Based on the Mozilla bug report, and subsequent patch, we can detect this situation via CVDisplayLinkGetCurrentCGDisplay(), so we follow the same approach, and then bail out: https://bugzilla.mozilla.org/show_bug.cgi?id=1201401#c158 Once we bail out we fall back to the timer based approach to delivering the update request. The next requestUpdate() will try to use the display link again, which will likely work this time around, as the display has had time to fully initialize. Change-Id: Ib80fd792516d1e4e7f863a82755cbf00d1eb6c34 Reviewed-by: Robert Griebl <robert.griebl@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> (cherry picked from commit ac0953c34d287e00559829e575b3308ccf46cb0b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm19
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm5
3 files changed, 20 insertions, 6 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h
index 435a6b95d8..267da96433 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.h
+++ b/src/plugins/platforms/cocoa/qcocoascreen.h
@@ -47,7 +47,7 @@ public:
static NSScreen *nativeScreenForDisplayId(CGDirectDisplayID displayId);
NSScreen *nativeScreen() const;
- void requestUpdate();
+ bool requestUpdate();
void deliverUpdateRequests();
bool isRunningDisplayLink() const;
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index 10b739d6d8..ba02aefea7 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -289,24 +289,33 @@ void QCocoaScreen::update(CGDirectDisplayID displayId)
Q_LOGGING_CATEGORY(lcQpaScreenUpdates, "qt.qpa.screen.updates", QtCriticalMsg);
-void QCocoaScreen::requestUpdate()
+bool QCocoaScreen::requestUpdate()
{
Q_ASSERT(m_displayId);
if (!isOnline()) {
qCDebug(lcQpaScreenUpdates) << this << "is not online. Ignoring update request";
- return;
+ return false;
}
if (!m_displayLink) {
- CVDisplayLinkCreateWithCGDisplay(m_displayId, &m_displayLink);
+ qCDebug(lcQpaScreenUpdates) << "Creating display link for" << this;
+ if (CVDisplayLinkCreateWithCGDisplay(m_displayId, &m_displayLink) != kCVReturnSuccess) {
+ qCWarning(lcQpaScreenUpdates) << "Failed to create display link for" << this;
+ return false;
+ }
+ if (auto displayId = CVDisplayLinkGetCurrentCGDisplay(m_displayLink); displayId != m_displayId) {
+ qCWarning(lcQpaScreenUpdates) << "Unexpected display" << displayId << "for display link";
+ CVDisplayLinkRelease(m_displayLink);
+ m_displayLink = nullptr;
+ return false;
+ }
CVDisplayLinkSetOutputCallback(m_displayLink, [](CVDisplayLinkRef, const CVTimeStamp*,
const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* displayLinkContext) -> int {
// FIXME: It would be nice if update requests would include timing info
static_cast<QCocoaScreen*>(displayLinkContext)->deliverUpdateRequests();
return kCVReturnSuccess;
}, this);
- qCDebug(lcQpaScreenUpdates) << "Display link created for" << this;
// During live window resizing -[NSWindow _resizeWithEvent:] will spin a local event loop
// in event-tracking mode, dequeuing only the mouse drag events needed to update the window's
@@ -361,6 +370,8 @@ void QCocoaScreen::requestUpdate()
qCDebug(lcQpaScreenUpdates) << "Starting display link for" << this;
CVDisplayLinkStart(m_displayLink);
}
+
+ return true;
}
// Helper to allow building up debug output in multiple steps
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 1d1f32213b..46a7ba20ba 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1531,7 +1531,10 @@ void QCocoaWindow::requestUpdate()
<< "using" << (updatesWithDisplayLink() ? "display-link" : "timer");
if (updatesWithDisplayLink()) {
- static_cast<QCocoaScreen *>(screen())->requestUpdate();
+ if (!static_cast<QCocoaScreen *>(screen())->requestUpdate()) {
+ qCDebug(lcQpaDrawing) << "Falling back to timer-based update request";
+ QPlatformWindow::requestUpdate();
+ }
} else {
// Fall back to the un-throttled timer-based callback
QPlatformWindow::requestUpdate();