Android: Release all windows when the application is suspended.
When an application is suspended on Android all its Gl surfaces are destroyed and can't be used to render anymore, so we should release them in order to give back to the system the memory used by them. [ChangeLog] [Android] Release all windows when the application is suspended. Task-number: QTBUG-29069 Change-Id: I038aaa2006da1f3188fccba943ec4ffb3e551cf0 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
This commit is contained in:
parent
734c126826
commit
96f0ff4f28
@ -418,6 +418,9 @@ namespace QtAndroid
|
||||
return;
|
||||
|
||||
m_surfaces.remove(surfaceId);
|
||||
if (m_surfaces.isEmpty())
|
||||
m_surfaceId = 1;
|
||||
|
||||
QJNIEnvironmentPrivate env;
|
||||
if (!env)
|
||||
return;
|
||||
|
@ -58,10 +58,10 @@ QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceForma
|
||||
|
||||
void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface)
|
||||
{
|
||||
QEGLPlatformContext::swapBuffers(surface);
|
||||
|
||||
if (surface->surface()->surfaceClass() == QSurface::Window)
|
||||
static_cast<QAndroidPlatformOpenGLWindow *>(surface)->checkNativeSurface(eglConfig());
|
||||
|
||||
QEGLPlatformContext::swapBuffers(surface);
|
||||
}
|
||||
|
||||
bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud()
|
||||
|
@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE
|
||||
QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display)
|
||||
:QAndroidPlatformWindow(window), m_eglDisplay(display)
|
||||
{
|
||||
lockSurface();
|
||||
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), bool(window->flags() & Qt::WindowStaysOnTopHint), 32);
|
||||
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
||||
unlockSurface();
|
||||
}
|
||||
|
||||
QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow()
|
||||
@ -97,6 +93,13 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
|
||||
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
||||
{
|
||||
QMutexLocker lock(&m_surfaceMutex);
|
||||
|
||||
if (m_nativeSurfaceId == -1) {
|
||||
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
|
||||
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
|
||||
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
||||
}
|
||||
|
||||
if (m_eglSurface == EGL_NO_SURFACE) {
|
||||
m_surfaceMutex.unlock();
|
||||
checkNativeSurface(config);
|
||||
@ -120,6 +123,20 @@ void QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
|
||||
}
|
||||
|
||||
void QAndroidPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState state)
|
||||
{
|
||||
QAndroidPlatformWindow::applicationStateChanged(state);
|
||||
if (state <= Qt::ApplicationHidden && QtAndroid::blockEventLoopsWhenSuspended()) {
|
||||
lockSurface();
|
||||
if (m_nativeSurfaceId != -1) {
|
||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
||||
m_nativeSurfaceId = -1;
|
||||
}
|
||||
clearEgl();
|
||||
unlockSurface();
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config)
|
||||
{
|
||||
clearEgl();
|
||||
|
@ -64,6 +64,8 @@ public:
|
||||
|
||||
void checkNativeSurface(EGLConfig config);
|
||||
|
||||
void applicationStateChanged(Qt::ApplicationState);
|
||||
|
||||
protected:
|
||||
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h);
|
||||
void createEgl(EGLConfig config);
|
||||
|
@ -54,6 +54,7 @@
|
||||
|
||||
#include <android/bitmap.h>
|
||||
#include <android/native_window_jni.h>
|
||||
#include <qguiapplication.h>
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QWindow>
|
||||
@ -102,6 +103,7 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
|
||||
m_redrawTimer.setSingleShot(true);
|
||||
m_redrawTimer.setInterval(0);
|
||||
connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw()));
|
||||
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged);
|
||||
}
|
||||
|
||||
QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
||||
@ -109,8 +111,7 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
||||
if (m_id != -1) {
|
||||
QtAndroid::destroySurface(m_id);
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
if (m_nativeSurface)
|
||||
ANativeWindow_release(m_nativeSurface);
|
||||
releaseSurface();
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +134,7 @@ QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
|
||||
|
||||
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent())
|
||||
if (window->parent() && window->isRaster())
|
||||
return;
|
||||
|
||||
m_windowStack.prepend(window);
|
||||
@ -149,10 +150,11 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
||||
|
||||
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent())
|
||||
if (window->parent() && window->isRaster())
|
||||
return;
|
||||
|
||||
m_windowStack.removeOne(window);
|
||||
|
||||
if (window->isRaster()) {
|
||||
m_rasterSurfaces.deref();
|
||||
setDirty(window->geometry());
|
||||
@ -165,7 +167,7 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
||||
|
||||
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent())
|
||||
if (window->parent() && window->isRaster())
|
||||
return;
|
||||
|
||||
int index = m_windowStack.indexOf(window);
|
||||
@ -182,7 +184,7 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
||||
|
||||
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent())
|
||||
if (window->parent() && window->isRaster())
|
||||
return;
|
||||
|
||||
int index = m_windowStack.indexOf(window);
|
||||
@ -247,14 +249,25 @@ void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
|
||||
}
|
||||
|
||||
if (m_id != -1) {
|
||||
if (m_nativeSurface) {
|
||||
ANativeWindow_release(m_nativeSurface);
|
||||
m_nativeSurface = 0;
|
||||
}
|
||||
releaseSurface();
|
||||
QtAndroid::setSurfaceGeometry(m_id, rect);
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::applicationStateChanged(Qt::ApplicationState state)
|
||||
{
|
||||
foreach (QAndroidPlatformWindow *w, m_windowStack)
|
||||
w->applicationStateChanged(state);
|
||||
|
||||
if (state <= Qt::ApplicationHidden && QtAndroid::blockEventLoopsWhenSuspended()) {
|
||||
lockSurface();
|
||||
QtAndroid::destroySurface(m_id);
|
||||
m_id = -1;
|
||||
releaseSurface();
|
||||
unlockSurface();
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
|
||||
{
|
||||
QtAndroidMenu::setActiveTopLevelWindow(w);
|
||||
@ -365,18 +378,22 @@ void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w,
|
||||
{
|
||||
lockSurface();
|
||||
if (surface && w && h) {
|
||||
if (m_nativeSurface)
|
||||
ANativeWindow_release(m_nativeSurface);
|
||||
releaseSurface();
|
||||
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
|
||||
QMetaObject::invokeMethod(this, "setDirty", Qt::QueuedConnection, Q_ARG(QRect, QRect(0, 0, w, h)));
|
||||
} else {
|
||||
if (m_nativeSurface) {
|
||||
ANativeWindow_release(m_nativeSurface);
|
||||
m_nativeSurface = 0;
|
||||
}
|
||||
releaseSurface();
|
||||
}
|
||||
unlockSurface();
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::releaseSurface()
|
||||
{
|
||||
if (m_nativeSurface) {
|
||||
ANativeWindow_release(m_nativeSurface);
|
||||
m_nativeSurface = 0;
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -107,6 +107,8 @@ private:
|
||||
Qt::ScreenOrientation orientation() const;
|
||||
Qt::ScreenOrientation nativeOrientation() const;
|
||||
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h);
|
||||
void releaseSurface();
|
||||
void applicationStateChanged(Qt::ApplicationState);
|
||||
|
||||
private slots:
|
||||
void doRedraw();
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include "qandroidplatformscreen.h"
|
||||
|
||||
#include "androidjnimain.h"
|
||||
|
||||
#include <qguiapplication.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -160,5 +162,21 @@ void QAndroidPlatformWindow::updateStatusBarVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
bool QAndroidPlatformWindow::isExposed() const
|
||||
{
|
||||
return qApp->applicationState() > Qt::ApplicationHidden
|
||||
&& window()->isVisible()
|
||||
&& !window()->geometry().isEmpty();
|
||||
}
|
||||
|
||||
void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState)
|
||||
{
|
||||
QRegion region;
|
||||
if (isExposed())
|
||||
region = QRect(QPoint(), geometry().size());
|
||||
|
||||
QWindowSystemInterface::handleExposeEvent(window(), region);
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -72,7 +72,9 @@ public:
|
||||
void requestActivateWindow();
|
||||
void updateStatusBarVisibility();
|
||||
inline bool isRaster() const { return window()->surfaceType() == QSurface::RasterSurface; }
|
||||
bool isExposed() const;
|
||||
|
||||
virtual void applicationStateChanged(Qt::ApplicationState);
|
||||
protected:
|
||||
void setGeometry(const QRect &rect);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user