From 3baa9aa3cd100d868313ce2920c35908abd172c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 5 Sep 2018 11:51:50 +0200 Subject: macOS: Clear NSOpenGLContex's drawable when using offscreen surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the user might accidentally render to the previously active window, if not explicitly using an FBO. This will have an performance impact if doing makeCurrent on a real window and an offscreen window back and forth with the same context, but that's not really a common or recommended use of QOffscreenSurface, as you can create FBOs with a normal window current as well. The use case of QOffscreenSurface is when a real window is not available. Change-Id: If93d04f82564523e15d5970429afea34c5cd31fe Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 50 +++++++++++++++----------- 1 file changed, 29 insertions(+), 21 deletions(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 2c8885e419..cf4ecd335c 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -331,34 +331,32 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) Q_ASSERT(surface->surface()->supportsOpenGL()); - if (surface->surface()->surfaceClass() == QSurface::Offscreen) { - [m_context makeCurrentContext]; - return true; - } - if (!setDrawable(surface)) return false; [m_context makeCurrentContext]; - // 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 - // when a high-resolution buffer is requested. This is not detectable using the NSWindow - // convertSizeToBacking and backingScaleFactor APIs. A typical result of this is that Qt - // will display a quarter of the window content when running in a virtual machine. - if (!m_didCheckForSoftwareContext) { - // FIXME: This ensures we check only once per context, - // but the context may be used for multiple surfaces. - m_didCheckForSoftwareContext = true; - - const GLubyte* renderer = glGetString(GL_RENDERER); - if (qstrcmp((const char *)renderer, "Apple Software Renderer") == 0) { - NSView *view = static_cast(surface)->m_view; - [view setWantsBestResolutionOpenGLSurface:NO]; + if (surface->surface()->surfaceClass() == QSurface::Window) { + // 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 + // when a high-resolution buffer is requested. This is not detectable using the NSWindow + // convertSizeToBacking and backingScaleFactor APIs. A typical result of this is that Qt + // will display a quarter of the window content when running in a virtual machine. + if (!m_didCheckForSoftwareContext) { + // FIXME: This ensures we check only once per context, + // but the context may be used for multiple surfaces. + m_didCheckForSoftwareContext = true; + + const GLubyte* renderer = glGetString(GL_RENDERER); + if (qstrcmp((const char *)renderer, "Apple Software Renderer") == 0) { + NSView *view = static_cast(surface)->m_view; + [view setWantsBestResolutionOpenGLSurface:NO]; + } } + + update(); } - update(); return true; } @@ -368,7 +366,17 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) */ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) { - Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window); + if (!surface || surface->surface()->surfaceClass() == QSurface::Offscreen) { + // Clear the current drawable and reset the active window, so that GL + // commands that don't target a specific FBO will not end up stomping + // on the previously set drawable. + qCDebug(lcQpaOpenGLContext) << "Clearing current drawable" << m_context.view << "for" << m_context; + [m_context clearDrawable]; + m_currentWindow.clear(); + return true; + } + + Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); QWindow *window = static_cast(surface)->window(); if (window == m_currentWindow.data()) -- cgit v1.2.3