diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-12-29 15:56:33 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-12-30 12:09:53 +0100 |
commit | db92f2f3aac60218756a1aa8811cf192acc0b0e6 (patch) | |
tree | f28a47aebb2f08e221fe7bffafce62a0a96cf7fd /src/plugins/platforms/ios/qioscontext.mm | |
parent | dd61a1d98ea9fbffeaf0e2adcd0ddd58105f6a75 (diff) | |
parent | 44da5b863597e761df3545dc7ff02a9b53bbb13d (diff) | |
download | qtbase-db92f2f3aac60218756a1aa8811cf192acc0b0e6.tar.gz |
Merge remote-tracking branch 'origin/5.9' into 5.10
Conflicts:
.qmake.conf
mkspecs/win32-g++/qmake.conf
src/corelib/global/qglobal_p.h
src/corelib/global/qoperatingsystemversion_p.h
src/corelib/io/qfilesystemengine_win.cpp
src/network/bearer/qbearerengine.cpp
src/platformsupport/input/libinput/qlibinputpointer.cpp
src/sql/doc/snippets/code/doc_src_sql-driver.cpp
src/widgets/kernel/qwidget_p.h
src/widgets/kernel/qwidgetwindow.cpp
src/widgets/styles/qfusionstyle.cpp
tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
Change-Id: I80e2722f481b12fff5d967c28f89208c0e9a1dd8
Diffstat (limited to 'src/plugins/platforms/ios/qioscontext.mm')
-rw-r--r-- | src/plugins/platforms/ios/qioscontext.mm | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 6a6cbb4324..03643c19a9 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -38,10 +38,13 @@ ****************************************************************************/ #include "qioscontext.h" + +#include "qiosintegration.h" #include "qioswindow.h" #include <dlfcn.h> +#include <QtGui/QGuiApplication> #include <QtGui/QOpenGLContext> #import <OpenGLES/EAGL.h> @@ -136,6 +139,9 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) { Q_ASSERT_IS_GL_SURFACE(surface); + if (!verifyGraphicsHardwareAvailability()) + return false; + [EAGLContext setCurrentContext:m_eaglContext]; // For offscreen surfaces we don't prepare a default FBO @@ -214,18 +220,12 @@ void QIOSContext::swapBuffers(QPlatformSurface *surface) { Q_ASSERT_IS_GL_SURFACE(surface); + if (!verifyGraphicsHardwareAvailability()) + return; + if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do - // When using threaded rendering, the render-thread may not have picked up - // yet on the fact that a window is no longer exposed, and will try to swap - // a non-exposed window. This may in some cases result in crashes, e.g. when - // iOS is suspending an application, so we have an extra guard here. - if (!static_cast<QIOSWindow *>(surface)->isExposed()) { - qCDebug(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush"); - return; - } - FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); Q_ASSERT_X(framebufferObject.isComplete, "QIOSContext", "swapBuffers on incomplete FBO"); @@ -287,6 +287,54 @@ bool QIOSContext::needsRenderbufferResize(QPlatformSurface *surface) const return false; } +bool QIOSContext::verifyGraphicsHardwareAvailability() +{ + // Per the iOS OpenGL ES Programming Guide, background apps may not execute commands on the + // graphics hardware. Specifically: "In your app delegate’s applicationDidEnterBackground: + // method, your app may want to delete some of its OpenGL ES objects to make memory and + // resources available to the foreground app. Call the glFinish function to ensure that + // the resources are removed immediately. After your app exits its applicationDidEnterBackground: + // method, it must not make any new OpenGL ES calls. If it makes an OpenGL ES call, it is + // terminated by iOS.". + static bool applicationBackgrounded = QGuiApplication::applicationState() == Qt::ApplicationSuspended; + + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState; + connect(applicationState, &QIOSApplicationState::applicationStateWillChange, [](Qt::ApplicationState state) { + if (applicationBackgrounded && state != Qt::ApplicationSuspended) { + qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled"; + applicationBackgrounded = false; + } + }); + connect(applicationState, &QIOSApplicationState::applicationStateDidChange, [](Qt::ApplicationState state) { + if (state != Qt::ApplicationSuspended) + return; + + qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled"; + applicationBackgrounded = true; + + // By the time we receive this signal the application has moved into + // Qt::ApplactionStateSuspended, and all windows have been obscured, + // which should stop all rendering. If there's still an active GL context, + // we follow Apple's advice and call glFinish before making it inactive. + if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) { + qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext; + glFinish(); + currentContext->doneCurrent(); + } + }); + }); + + if (applicationBackgrounded) { + static const char warning[] = "OpenGL ES calls are not allowed while an application is backgrounded"; + Q_ASSERT_X(!applicationBackgrounded, "QIOSContext", warning); + qCWarning(lcQpaGLContext, warning); + } + + return !applicationBackgrounded; +} + void QIOSContext::windowDestroyed(QObject *object) { QIOSWindow *window = static_cast<QIOSWindow *>(object); |