diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoaglcontext.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaglcontext.mm | 117 |
1 files changed, 34 insertions, 83 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index c2fcb6cdbc..a65311175f 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <AppKit/AppKit.h> @@ -44,6 +8,8 @@ #include "qcocoahelpers.h" #include "qcocoascreen.h" +#include <QtCore/private/qcore_mac_p.h> + #include <qdebug.h> #include <dlfcn.h> @@ -393,7 +359,13 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) if (view == QT_IGNORE_DEPRECATIONS(m_context.view)) return true; - prepareDrawable(cocoaWindow); + // We generally want high-DPI GL surfaces, unless the user has explicitly disabled them. + // According to the documentation, layer-backed views ignore wantsBestResolutionOpenGLSurface + // and configure their own backing surface at an appropriate resolution, but in some cases + // we've seen this fail (plugin views embedded in surface-backed hosts), so we do it anyways. + QT_IGNORE_DEPRECATIONS(view.wantsBestResolutionOpenGLSurface) = qt_mac_resolveOption(YES, + cocoaWindow->window(), "_q_mac_wantsBestResolutionOpenGLSurface", + "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); // Setting the drawable may happen on a separate thread as a result of // a call to makeCurrent, so we need to set up the observers before we @@ -410,16 +382,21 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) m_updateObservers.clear(); - if (view.layer) { - m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback)); - m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback)); - } else { - m_updateObservers.append(QMacNotificationObserver(view, QT_IGNORE_DEPRECATIONS(NSViewGlobalFrameDidChangeNotification), updateCallback)); - } + m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback)); + m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback)); m_updateObservers.append(QMacNotificationObserver([NSApplication sharedApplication], NSApplicationDidChangeScreenParametersNotification, updateCallback)); + m_updateObservers.append(QMacNotificationObserver(view, + QCocoaWindowWillReleaseQNSViewNotification, [this, view] { + if (QT_IGNORE_DEPRECATIONS(m_context.view) != view) + return; + qCDebug(lcQpaOpenGLContext) << view << "about to be released." + << "Clearing current drawable for" << m_context; + [m_context clearDrawable]; + })); + // If any of the observers fire at this point it's fine. We check the // view association (atomically) in the update callback, and skip the // update if we haven't associated yet. Setting the drawable below will @@ -437,34 +414,10 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) return true; } -void QCocoaGLContext::prepareDrawable(QCocoaWindow *platformWindow) -{ - // We generally want high-DPI GL surfaces, unless the user has explicitly disabled them - bool prefersBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, - platformWindow->window(), "_q_mac_wantsBestResolutionOpenGLSurface", - "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); - - auto *view = platformWindow->view(); - - // The only case we have to opt out ourselves is when using the Apple software renderer - // in combination with surface-backed views, as these together do not support high-DPI. - if (prefersBestResolutionOpenGLSurface) { - int rendererID = 0; - [m_context getValues:&rendererID forParameter:NSOpenGLContextParameterCurrentRendererID]; - bool isSoftwareRenderer = (rendererID & kCGLRendererIDMatchingMask) == kCGLRendererGenericFloatID; - if (isSoftwareRenderer && !view.layer) { - qCInfo(lcQpaOpenGLContext) << "Disabling high resolution GL surface due to software renderer"; - prefersBestResolutionOpenGLSurface = false; - } - } - - QT_IGNORE_DEPRECATIONS(view.wantsBestResolutionOpenGLSurface) = prefersBestResolutionOpenGLSurface; -} - // NSOpenGLContext is not re-entrant. Even when using separate contexts per thread, // view, and window, calls into the API will still deadlock. For more information // see https://openradar.appspot.com/37064579 -static QMutex s_reentrancyMutex; +Q_CONSTINIT static QMutex s_reentrancyMutex; void QCocoaGLContext::update() { @@ -494,19 +447,17 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) return; } - if (QT_IGNORE_DEPRECATIONS(m_context.view).layer) { - // Flushing an NSOpenGLContext will hit the screen immediately, ignoring - // any Core Animation transactions in place. This may result in major - // visual artifacts if the flush happens out of sync with the size - // of the layer, view, and window reflected by other parts of the UI, - // e.g. if the application flushes in the resize event or a timer during - // window resizing, instead of in the expose event. - auto *cocoaWindow = static_cast<QCocoaWindow *>(surface); - if (cocoaWindow->geometry().size() != cocoaWindow->m_exposedRect.size()) { - qCInfo(lcQpaOpenGLContext) << "Window exposed size does not match geometry (yet)." - << "Skipping flush to avoid visual artifacts."; - return; - } + // Flushing an NSOpenGLContext will hit the screen immediately, ignoring + // any Core Animation transactions in place. This may result in major + // visual artifacts if the flush happens out of sync with the size + // of the layer, view, and window reflected by other parts of the UI, + // e.g. if the application flushes in the resize event or a timer during + // window resizing, instead of in the expose event. + auto *cocoaWindow = static_cast<QCocoaWindow *>(surface); + if (cocoaWindow->geometry().size() != cocoaWindow->m_exposedRect.size()) { + qCInfo(lcQpaOpenGLContext) << "Window exposed size does not match geometry (yet)." + << "Skipping flush to avoid visual artifacts."; + return; } QMutexLocker locker(&s_reentrancyMutex); |