From 2697148775703883ae700b15d4efe240050273a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 22 Oct 2018 13:04:42 +0200 Subject: macOS: Only enable layer-backed views on 10.14 if built against 10.14 SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of explicitly enabling layer-backing for Qt 5.12 on all macOS version, we follow the macOS default to enable it for 10.14 if the application binary was built against the 10.14 SDK. Aligning ourselves with Apple's switch to forced layer-backing means we have an easier story when it comes to supporting different runtime configurations. Fixes: QTBUG-71499 Change-Id: I34ee49b3daeb6ed8df444a3759d3573ebc9ea30f Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qnsview.mm | 15 +------ src/plugins/platforms/cocoa/qnsview_drawing.mm | 61 +++++++++++++++++++++----- 2 files changed, 53 insertions(+), 23 deletions(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9bd53ed334..540f701d43 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -71,7 +71,7 @@ @end @interface QT_MANGLE_NAMESPACE(QNSView) (Drawing) -- (BOOL)wantsLayerHelper; +- (void)initDrawing; @end @interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject @@ -152,19 +152,8 @@ self.focusRingType = NSFocusRingTypeNone; self.cursor = nil; - self.wantsLayer = [self wantsLayerHelper]; - - // Enable high-DPI OpenGL for retina displays. Enabling has the side - // effect that Cocoa will start calling glViewport(0, 0, width, height), - // overriding any glViewport calls in application code. This is usually not a - // problem, except if the application wants to have a "custom" viewport. - // (like the hellogl example) - if (m_platformWindow->window()->supportsOpenGL()) { - self.wantsBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, m_platformWindow->window(), - "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); - // See also QCocoaGLContext::makeCurrent for software renderer workarounds. - } + [self initDrawing]; [self registerDragTypes]; [[NSNotificationCenter defaultCenter] addObserver:self diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm index 4f9d17504d..e9af90a45c 100644 --- a/src/plugins/platforms/cocoa/qnsview_drawing.mm +++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm @@ -41,6 +41,24 @@ @implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing) +- (void)initDrawing +{ + self.wantsLayer = [self layerExplicitlyRequested] + || [self shouldUseMetalLayer] + || [self layerEnabledByMacOS]; + + // Enable high-DPI OpenGL for retina displays. Enabling has the side + // effect that Cocoa will start calling glViewport(0, 0, width, height), + // overriding any glViewport calls in application code. This is usually not a + // problem, except if the application wants to have a "custom" viewport. + // (like the hellogl example) + if (m_platformWindow->window()->supportsOpenGL()) { + self.wantsBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, m_platformWindow->window(), + "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); + // See also QCocoaGLContext::makeCurrent for software renderer workarounds. + } +} + - (BOOL)isOpaque { if (!m_platformWindow) @@ -71,23 +89,38 @@ m_platformWindow->handleExposeEvent(exposedRegion); } -- (BOOL)shouldUseMetalLayer +- (BOOL)layerEnabledByMacOS { - // MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK) - QSurface::SurfaceType surfaceType = m_platformWindow->window()->surfaceType(); - return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface; + // AppKit has its own logic for this, but if we rely on that, our layers are created + // by AppKit at a point where we've already set up other parts of the platform plugin + // based on the presence of layers or not. Once we've rewritten these parts to support + // dynamically picking up layer enablement we can let AppKit do its thing. + return QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave + && QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave; } -- (BOOL)wantsLayerHelper +- (BOOL)layerExplicitlyRequested { - Q_ASSERT(m_platformWindow); + static bool wantsLayer = [&]() { + int wantsLayer = qt_mac_resolveOption(-1, m_platformWindow->window(), + "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER"); - bool wantsLayer = qt_mac_resolveOption(true, m_platformWindow->window(), - "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER"); + if (wantsLayer != -1 && [self layerEnabledByMacOS]) { + qCWarning(lcQpaDrawing) << "Layer-backing can not be explicitly controlled on 10.14 when built against the 10.14 SDK"; + return true; + } - bool layerForSurfaceType = [self shouldUseMetalLayer]; + return wantsLayer == 1; + }(); - return wantsLayer || layerForSurfaceType; + return wantsLayer; +} + +- (BOOL)shouldUseMetalLayer +{ + // MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK) + QSurface::SurfaceType surfaceType = m_platformWindow->window()->surfaceType(); + return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface; } - (CALayer *)makeBackingLayer @@ -115,6 +148,14 @@ return [super makeBackingLayer]; } +- (void)setLayer:(CALayer *)layer +{ + qCDebug(lcQpaDrawing) << "Making" << self << "layer-backed with" << layer + << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested" + : [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS"); + [super setLayer:layer]; +} + - (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy { // We need to set this explicitly since the super implementation -- cgit v1.2.3 From ee3c66ca917b77f759acea7c6b27d15066f0b814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 12 Nov 2018 15:29:33 +0100 Subject: macOS: Disable threaded GL rendering on SDK 10.14+ AppKit expects rendering to happen on the main thread, or at least any interaction with AppKit UI classes such as NSView. Our OpenGL helpers, such as QOpenGLContext, do not enforce this, and we may end up calling into AppKit UI classes on the render thread, deadlocking the application. Until this can be investigated and new APIs possibly introduced that allow a more fine grained control in our own classes, we disable threaded GL as a capability of the platform, which will inform clients such as QtQuick to use the basic render loop. [ChangeLog][macOS] Threaded OpenGL usage has been disabled when building using Xcode 10/SDK 10.14 and later. Qt Quick defaults to the 'basic' render loop now on macOS. Task-number: QTBUG-71731 Change-Id: I6fc3295e833ecd48ad49382b8275c762fa7978a6 Reviewed-by: Laszlo Agocs Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 936fecf8de..1bd1029863 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -340,12 +340,17 @@ QCocoaScreen *QCocoaIntegration::screenForNSScreen(NSScreen *nsScreen) bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { - case ThreadedPixmaps: #ifndef QT_NO_OPENGL - case OpenGL: case ThreadedOpenGL: + // AppKit expects rendering to happen on the main thread, and we can + // easily end up in situations where rendering on secondary threads + // will result in visual artifacts, bugs, or even deadlocks, when + // building with SDK 10.14 or higher which enbles view layer-backing. + return QMacVersion::buildSDK() < QOperatingSystemVersion(QOperatingSystemVersion::MacOSMojave); + case OpenGL: case BufferQueueingOpenGL: #endif + case ThreadedPixmaps: case WindowMasks: case MultipleWindows: case ForeignWindows: -- cgit v1.2.3