From 2b1f01426c1ee47474b4b8e4e53799d992d0711c Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 7 Jan 2016 13:20:08 +0100 Subject: WinRT: Fix application shutdown Do not create a dummy eglDisplay when the global static is constructed. This causes ANGLE to wrongly set some internals, which breaks usage of EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE as the attribute map might be empty after calling eglGetPlatformDisplayEXT. Furthermore initialize() assigns a new display to it without terminating the old one. This way, the internal suspend handler in ANGLE (Trim11.cpp) will be added to the application. The suspend handler is not invoked when an application suspends though. Reason being that the handler needs to be added from inside the Xaml thread. As we cannot control this inside ANGLE, we will call eglInitialize inside the Xaml thread and hence get the suspend event properly. Task-number: QTBUG-50337 Task-number: QTBUG-50292 Change-Id: I3867377254c37084bf24f18e78af467f6237db57 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrteglcontext.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/plugins/platforms/winrt') diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index 3fd0278360..ebd15d7184 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -54,9 +54,6 @@ QT_BEGIN_NAMESPACE struct WinRTEGLDisplay { WinRTEGLDisplay() { - eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (eglDisplay == EGL_NO_DISPLAY) - qCritical("Failed to initialize EGL display: 0x%x", eglGetError()); } ~WinRTEGLDisplay() { eglTerminate(eglDisplay); @@ -117,9 +114,17 @@ void QWinRTEGLContext::initialize() if (g->eglDisplay == EGL_NO_DISPLAY) qCritical("Failed to initialize EGL display: 0x%x", eglGetError()); - if (!eglInitialize(g->eglDisplay, nullptr, nullptr)) - qCritical("Failed to initialize EGL: 0x%x", eglGetError()); - + // eglInitialize checks for EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE + // which adds a suspending handler. This needs to be added from the Xaml + // thread itself, otherwise it will not be invoked. add_Suspending does + // not return an error unfortunately, so it silently fails and causes + // applications to not quit when the system wants to terminate the app + // after suspend. + hr = QEventDispatcherWinRT::runOnXamlThread([]() { + if (!eglInitialize(g->eglDisplay, nullptr, nullptr)) + qCritical("Failed to initialize EGL: 0x%x", eglGetError()); + return S_OK; + }); d->eglConfig = q_configFromGLFormat(g->eglDisplay, d->format); const EGLint flags = d->format.testOption(QSurfaceFormat::DebugContext) -- cgit v1.2.3 From c4ecab7127807eddd820b5c747a805cf5b0fd06d Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 7 Jan 2016 13:32:09 +0100 Subject: WinRT: Invoke correct remove handler Probably a typo when moving to Xaml. Change-Id: I0739f4561912e1e16df7b124d6d187cd0f60f657 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms/winrt') diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index e94a0aa846..93757d293c 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -124,7 +124,7 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate) IID_PPV_ARGS(&d->application)); Q_ASSERT_SUCCEEDED(hr); hr = d->application->add_Suspending(Callback(this, &QWinRTIntegration::onSuspended).Get(), - &d->applicationTokens[&ICoreApplication::remove_Resuming]); + &d->applicationTokens[&ICoreApplication::remove_Suspending]); Q_ASSERT_SUCCEEDED(hr); hr = d->application->add_Resuming(Callback(this, &QWinRTIntegration::onResume).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]); -- cgit v1.2.3 From becbffe291c1105eb422e8dc66c67c5b6443b96c Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 8 Jan 2016 12:50:32 +0100 Subject: winphone: Properly close the application When shutting down an application on Windows Phone the SceneGraph tries to create an offscreen surface to render into. If there is no offscreen surface available, it creates a new native window and tries to hide it. As the native event loop is about to shut down, creation fails and exceptions are raised. Instead we create a vanilla QPlatformOffscreenSurface. The SceneGraph recognizes it as such and can handle a proper cleanup on its own. Furthermore removing the suspend/resume handler in the destructor of QWinRTIntegration fails for Windows Phone as the application object itself does not accept this anymore. Hence skip this part for this platform. Task-number: QTBUG-49310 Change-Id: I02acdd5a635ef0b9d6ef8199376537b8f0f1a8fb Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrteglcontext.cpp | 4 ++++ src/plugins/platforms/winrt/qwinrtintegration.cpp | 17 +++++++++++++++++ src/plugins/platforms/winrt/qwinrtintegration.h | 1 + 3 files changed, 22 insertions(+) (limited to 'src/plugins/platforms/winrt') diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index ebd15d7184..bc77df566e 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -46,6 +46,7 @@ #define EGL_EGLEXT_PROTOTYPES #include +#include #include #include @@ -147,6 +148,9 @@ bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface) Q_D(QWinRTEGLContext); Q_ASSERT(windowSurface->surface()->supportsOpenGL()); + if (windowSurface->surface()->surfaceClass() == QSurface::Offscreen) + return false; + QWinRTWindow *window = static_cast(windowSurface); if (window->eglSurface() == EGL_NO_SURFACE) window->createEglSurface(g->eglDisplay, d->eglConfig); diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 93757d293c..71e92f33ca 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -49,6 +49,8 @@ #include #include +#include + #include #include #include @@ -180,10 +182,15 @@ QWinRTIntegration::~QWinRTIntegration() Q_ASSERT_SUCCEEDED(hr); } #endif + // Do not execute this on Windows Phone as the application is already + // shutting down and trying to unregister suspending/resume handler will + // cause exceptions and assert in debug mode +#ifndef Q_OS_WINPHONE for (QHash::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i) { hr = (d->application.Get()->*i.key())(i.value()); Q_ASSERT_SUCCEEDED(hr); } +#endif destroyScreen(d->mainScreen); Windows::Foundation::Uninitialize(); } @@ -349,4 +356,14 @@ HRESULT QWinRTIntegration::onResume(IInspectable *, IInspectable *) return S_OK; } +QPlatformOffscreenSurface *QWinRTIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + // This is only used for shutdown of applications. + // In case we do not return an empty surface the scenegraph will try + // to create a new native window during application exit causing crashes + // or assertions. + return new QPlatformOffscreenSurface(surface); +} + + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 5456f6922f..31a3ce7c1c 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -98,6 +98,7 @@ public: QStringList themeNames() const Q_DECL_OVERRIDE; QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; private: #ifdef Q_OS_WINPHONE HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args); -- cgit v1.2.3 From 0355345398ab1bfc46d56ebab7afbb91afc74ee4 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 8 Jan 2016 18:08:36 +0100 Subject: winrt: Flush the system event queue when adding/removing windows This has only been identified by WACK for Windows 10. QWinRTWindow::setVisible adds a Window to the screen and immediately tries to set the native visibility. This only works when the system events are handled immediately. While this is the case most of the time, certification tests revealed that this is not always the case. We have to flush before setting the element visibility. Change-Id: Ifce4c045c185c57bc386a4e832074fb84f5d0053 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/plugins/platforms/winrt') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index a642443386..997aa0d86c 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -779,6 +779,7 @@ void QWinRTScreen::addWindow(QWindow *window) d->visibleWindows.prepend(window); QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); + QWindowSystemInterface::flushWindowSystemEvents(); } void QWinRTScreen::removeWindow(QWindow *window) @@ -796,6 +797,7 @@ void QWinRTScreen::removeWindow(QWindow *window) if (wasTopWindow) QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); + QWindowSystemInterface::flushWindowSystemEvents(); } void QWinRTScreen::raise(QWindow *window) -- cgit v1.2.3