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;
|
return;
|
||||||
|
|
||||||
m_surfaces.remove(surfaceId);
|
m_surfaces.remove(surfaceId);
|
||||||
|
if (m_surfaces.isEmpty())
|
||||||
|
m_surfaceId = 1;
|
||||||
|
|
||||||
QJNIEnvironmentPrivate env;
|
QJNIEnvironmentPrivate env;
|
||||||
if (!env)
|
if (!env)
|
||||||
return;
|
return;
|
||||||
|
@ -58,10 +58,10 @@ QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceForma
|
|||||||
|
|
||||||
void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface)
|
void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface)
|
||||||
{
|
{
|
||||||
QEGLPlatformContext::swapBuffers(surface);
|
|
||||||
|
|
||||||
if (surface->surface()->surfaceClass() == QSurface::Window)
|
if (surface->surface()->surfaceClass() == QSurface::Window)
|
||||||
static_cast<QAndroidPlatformOpenGLWindow *>(surface)->checkNativeSurface(eglConfig());
|
static_cast<QAndroidPlatformOpenGLWindow *>(surface)->checkNativeSurface(eglConfig());
|
||||||
|
|
||||||
|
QEGLPlatformContext::swapBuffers(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud()
|
bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud()
|
||||||
|
@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display)
|
QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display)
|
||||||
:QAndroidPlatformWindow(window), m_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()
|
QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow()
|
||||||
@ -97,6 +93,13 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
|
|||||||
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&m_surfaceMutex);
|
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) {
|
if (m_eglSurface == EGL_NO_SURFACE) {
|
||||||
m_surfaceMutex.unlock();
|
m_surfaceMutex.unlock();
|
||||||
checkNativeSurface(config);
|
checkNativeSurface(config);
|
||||||
@ -120,6 +123,20 @@ void QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
|
|||||||
QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
|
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)
|
void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config)
|
||||||
{
|
{
|
||||||
clearEgl();
|
clearEgl();
|
||||||
|
@ -64,6 +64,8 @@ public:
|
|||||||
|
|
||||||
void checkNativeSurface(EGLConfig config);
|
void checkNativeSurface(EGLConfig config);
|
||||||
|
|
||||||
|
void applicationStateChanged(Qt::ApplicationState);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h);
|
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h);
|
||||||
void createEgl(EGLConfig config);
|
void createEgl(EGLConfig config);
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
#include <android/bitmap.h>
|
#include <android/bitmap.h>
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
|
#include <qguiapplication.h>
|
||||||
|
|
||||||
#include <QtGui/QGuiApplication>
|
#include <QtGui/QGuiApplication>
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
@ -102,6 +103,7 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
|
|||||||
m_redrawTimer.setSingleShot(true);
|
m_redrawTimer.setSingleShot(true);
|
||||||
m_redrawTimer.setInterval(0);
|
m_redrawTimer.setInterval(0);
|
||||||
connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw()));
|
connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw()));
|
||||||
|
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
||||||
@ -109,8 +111,7 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
|||||||
if (m_id != -1) {
|
if (m_id != -1) {
|
||||||
QtAndroid::destroySurface(m_id);
|
QtAndroid::destroySurface(m_id);
|
||||||
m_surfaceWaitCondition.wakeOne();
|
m_surfaceWaitCondition.wakeOne();
|
||||||
if (m_nativeSurface)
|
releaseSurface();
|
||||||
ANativeWindow_release(m_nativeSurface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +134,7 @@ QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
|
|||||||
|
|
||||||
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
||||||
{
|
{
|
||||||
if (window->parent())
|
if (window->parent() && window->isRaster())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_windowStack.prepend(window);
|
m_windowStack.prepend(window);
|
||||||
@ -149,10 +150,11 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
|||||||
|
|
||||||
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
||||||
{
|
{
|
||||||
if (window->parent())
|
if (window->parent() && window->isRaster())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_windowStack.removeOne(window);
|
m_windowStack.removeOne(window);
|
||||||
|
|
||||||
if (window->isRaster()) {
|
if (window->isRaster()) {
|
||||||
m_rasterSurfaces.deref();
|
m_rasterSurfaces.deref();
|
||||||
setDirty(window->geometry());
|
setDirty(window->geometry());
|
||||||
@ -165,7 +167,7 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
|||||||
|
|
||||||
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
||||||
{
|
{
|
||||||
if (window->parent())
|
if (window->parent() && window->isRaster())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int index = m_windowStack.indexOf(window);
|
int index = m_windowStack.indexOf(window);
|
||||||
@ -182,7 +184,7 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
|||||||
|
|
||||||
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
||||||
{
|
{
|
||||||
if (window->parent())
|
if (window->parent() && window->isRaster())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int index = m_windowStack.indexOf(window);
|
int index = m_windowStack.indexOf(window);
|
||||||
@ -247,14 +249,25 @@ void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_id != -1) {
|
if (m_id != -1) {
|
||||||
if (m_nativeSurface) {
|
releaseSurface();
|
||||||
ANativeWindow_release(m_nativeSurface);
|
|
||||||
m_nativeSurface = 0;
|
|
||||||
}
|
|
||||||
QtAndroid::setSurfaceGeometry(m_id, rect);
|
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)
|
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
|
||||||
{
|
{
|
||||||
QtAndroidMenu::setActiveTopLevelWindow(w);
|
QtAndroidMenu::setActiveTopLevelWindow(w);
|
||||||
@ -365,18 +378,22 @@ void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w,
|
|||||||
{
|
{
|
||||||
lockSurface();
|
lockSurface();
|
||||||
if (surface && w && h) {
|
if (surface && w && h) {
|
||||||
if (m_nativeSurface)
|
releaseSurface();
|
||||||
ANativeWindow_release(m_nativeSurface);
|
|
||||||
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
|
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
|
||||||
QMetaObject::invokeMethod(this, "setDirty", Qt::QueuedConnection, Q_ARG(QRect, QRect(0, 0, w, h)));
|
QMetaObject::invokeMethod(this, "setDirty", Qt::QueuedConnection, Q_ARG(QRect, QRect(0, 0, w, h)));
|
||||||
} else {
|
} else {
|
||||||
if (m_nativeSurface) {
|
releaseSurface();
|
||||||
ANativeWindow_release(m_nativeSurface);
|
|
||||||
m_nativeSurface = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unlockSurface();
|
unlockSurface();
|
||||||
m_surfaceWaitCondition.wakeOne();
|
m_surfaceWaitCondition.wakeOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QAndroidPlatformScreen::releaseSurface()
|
||||||
|
{
|
||||||
|
if (m_nativeSurface) {
|
||||||
|
ANativeWindow_release(m_nativeSurface);
|
||||||
|
m_nativeSurface = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -107,6 +107,8 @@ private:
|
|||||||
Qt::ScreenOrientation orientation() const;
|
Qt::ScreenOrientation orientation() const;
|
||||||
Qt::ScreenOrientation nativeOrientation() const;
|
Qt::ScreenOrientation nativeOrientation() const;
|
||||||
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h);
|
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h);
|
||||||
|
void releaseSurface();
|
||||||
|
void applicationStateChanged(Qt::ApplicationState);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void doRedraw();
|
void doRedraw();
|
||||||
|
@ -45,6 +45,8 @@
|
|||||||
#include "qandroidplatformscreen.h"
|
#include "qandroidplatformscreen.h"
|
||||||
|
|
||||||
#include "androidjnimain.h"
|
#include "androidjnimain.h"
|
||||||
|
|
||||||
|
#include <qguiapplication.h>
|
||||||
#include <qpa/qwindowsysteminterface.h>
|
#include <qpa/qwindowsysteminterface.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -72,7 +72,9 @@ public:
|
|||||||
void requestActivateWindow();
|
void requestActivateWindow();
|
||||||
void updateStatusBarVisibility();
|
void updateStatusBarVisibility();
|
||||||
inline bool isRaster() const { return window()->surfaceType() == QSurface::RasterSurface; }
|
inline bool isRaster() const { return window()->surfaceType() == QSurface::RasterSurface; }
|
||||||
|
bool isExposed() const;
|
||||||
|
|
||||||
|
virtual void applicationStateChanged(Qt::ApplicationState);
|
||||||
protected:
|
protected:
|
||||||
void setGeometry(const QRect &rect);
|
void setGeometry(const QRect &rect);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user