macOS: Propagate [NSOpenGLContext setView:] failures
Instead of trying to mask situations where [NSOpenGLContext setView:] will fail (such as calling it for a view that's not part of a window yet, or part of a window that hasn't been shown), we report the error up through the API, so that QOpenGLContext::makeCurrent() will return false. This is documented to occur e.g. when "the surface is not exposed, or the graphics hardware is not available due to e.g. the application being suspended." QGLWidget was taught how to deal with this situation inbb10cc27a50e. Other Qt APIs seem to handle it fine, but if regressions occur they should be fixable though the same logic as incc27a50e. Change-Id: I92775fc165444696b6c5b44fa0e28ce3c4ad2190 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
parent
68f20bb8f4
commit
f8b17a297e
|
|
@ -75,7 +75,7 @@ public:
|
|||
private:
|
||||
static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(const QSurfaceFormat &format);
|
||||
|
||||
void setActiveWindow(QWindow *window);
|
||||
bool setActiveWindow(QWindow *window);
|
||||
void updateSurfaceFormat();
|
||||
|
||||
NSOpenGLContext *m_context;
|
||||
|
|
|
|||
|
|
@ -376,7 +376,10 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
|
|||
return true;
|
||||
|
||||
QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
|
||||
setActiveWindow(window);
|
||||
if (!setActiveWindow(window)) {
|
||||
qCDebug(lcQpaOpenGLContext) << "Failed to activate window, skipping makeCurrent";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable high-resolution surfaces when using the software renderer, which has the
|
||||
// problem that the system silently falls back to a to using a low-resolution buffer
|
||||
|
|
@ -397,23 +400,29 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
|
|||
return true;
|
||||
}
|
||||
|
||||
void QCocoaGLContext::setActiveWindow(QWindow *window)
|
||||
bool QCocoaGLContext::setActiveWindow(QWindow *window)
|
||||
{
|
||||
if (window == m_currentWindow.data())
|
||||
return;
|
||||
return true;
|
||||
|
||||
Q_ASSERT(window->handle());
|
||||
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
|
||||
NSView *view = cocoaWindow->view();
|
||||
|
||||
if ((m_context.view = view) != view) {
|
||||
qCDebug(lcQpaOpenGLContext) << "Associating" << view << "with" << m_context << "failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(lcQpaOpenGLContext) << m_context << "now associated with" << m_context.view;
|
||||
|
||||
if (m_currentWindow && m_currentWindow.data()->handle())
|
||||
static_cast<QCocoaWindow *>(m_currentWindow.data()->handle())->setCurrentContext(0);
|
||||
|
||||
Q_ASSERT(window->handle());
|
||||
|
||||
m_currentWindow = window;
|
||||
|
||||
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
|
||||
cocoaWindow->setCurrentContext(this);
|
||||
|
||||
Q_ASSERT(!cocoaWindow->isForeignWindow());
|
||||
[qnsview_cast(cocoaWindow->view()) setQCocoaGLContext:this];
|
||||
return true;
|
||||
}
|
||||
|
||||
// NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579)
|
||||
|
|
@ -431,7 +440,10 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
|
|||
return; // Nothing to do
|
||||
|
||||
QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
|
||||
setActiveWindow(window);
|
||||
if (!setActiveWindow(window)) {
|
||||
qCWarning(lcQpaOpenGLContext) << "Failed to activate window, skipping swapBuffers";
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker locker(&s_contextMutex);
|
||||
[m_context flushBuffer];
|
||||
|
|
|
|||
|
|
@ -64,12 +64,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem));
|
|||
|
||||
@end
|
||||
|
||||
@interface QT_MANGLE_NAMESPACE(QNSView) (DrawingAPI)
|
||||
#ifndef QT_NO_OPENGL
|
||||
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
|
||||
#endif
|
||||
@end
|
||||
|
||||
@interface QT_MANGLE_NAMESPACE(QNSView) (MouseAPI)
|
||||
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent;
|
||||
- (void)resetMouseButtons;
|
||||
|
|
|
|||
|
|
@ -122,10 +122,6 @@
|
|||
bool m_dontOverrideCtrlLMB;
|
||||
bool m_sendUpAsRightButton;
|
||||
Qt::KeyboardModifiers m_currentWheelModifiers;
|
||||
#ifndef QT_NO_OPENGL
|
||||
QCocoaGLContext *m_glContext;
|
||||
bool m_shouldSetGLContextinDrawRect;
|
||||
#endif
|
||||
NSString *m_inputSource;
|
||||
QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
|
||||
bool m_resendKeyEvent;
|
||||
|
|
@ -143,10 +139,6 @@
|
|||
m_acceptedMouseDowns = Qt::NoButton;
|
||||
m_frameStrutButtons = Qt::NoButton;
|
||||
m_sendKeyEvent = false;
|
||||
#ifndef QT_NO_OPENGL
|
||||
m_glContext = nullptr;
|
||||
m_shouldSetGLContextinDrawRect = false;
|
||||
#endif
|
||||
m_sendUpAsRightButton = false;
|
||||
m_inputSource = nil;
|
||||
m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self];
|
||||
|
|
|
|||
|
|
@ -39,22 +39,6 @@
|
|||
|
||||
// This file is included from qnsview.mm, and only used to organize the code
|
||||
|
||||
@implementation QT_MANGLE_NAMESPACE(QNSView) (DrawingAPI)
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
- (void)setQCocoaGLContext:(QCocoaGLContext *)context
|
||||
{
|
||||
m_glContext = context;
|
||||
[m_glContext->nsOpenGLContext() setView:self];
|
||||
if (![m_glContext->nsOpenGLContext() view]) {
|
||||
//was unable to set view
|
||||
m_shouldSetGLContextinDrawRect = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing)
|
||||
|
||||
- (BOOL)isOpaque
|
||||
|
|
@ -84,19 +68,7 @@
|
|||
exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
|
||||
|
||||
qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
|
||||
[self updateRegion:exposedRegion];
|
||||
}
|
||||
|
||||
- (void)updateRegion:(QRegion)dirtyRegion
|
||||
{
|
||||
#ifndef QT_NO_OPENGL
|
||||
if (m_glContext && m_shouldSetGLContextinDrawRect) {
|
||||
[m_glContext->nsOpenGLContext() setView:self];
|
||||
m_shouldSetGLContextinDrawRect = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_platformWindow->handleExposeEvent(dirtyRegion);
|
||||
m_platformWindow->handleExposeEvent(exposedRegion);
|
||||
}
|
||||
|
||||
- (BOOL)shouldUseMetalLayer
|
||||
|
|
@ -174,7 +146,7 @@
|
|||
qCDebug(lcQpaDrawing) << "[QNSView displayLayer]" << m_platformWindow->window();
|
||||
|
||||
// FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
|
||||
[self updateRegion:QRectF::fromCGRect(self.bounds).toRect()];
|
||||
m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
|
||||
}
|
||||
|
||||
- (void)viewDidChangeBackingProperties
|
||||
|
|
|
|||
Loading…
Reference in New Issue