summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBogDan Vatra <bogdan@kde.org>2014-07-21 17:09:31 +0300
committerBogDan Vatra <bogdan@kde.org>2014-07-31 19:20:42 +0200
commit96f0ff4f28c92b529a4d79afa669917734ec1192 (patch)
tree24dc77e2e40010374cb4b190b849414f04815e99 /src
parent734c1268269a71b16829d36179e4a090f76c785e (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp3
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglcontext.cpp4
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.cpp25
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp49
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp18
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h2
8 files changed, 83 insertions, 22 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 4ee32d79c2..7b99b29132 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -418,6 +418,9 @@ namespace QtAndroid
return;
m_surfaces.remove(surfaceId);
+ if (m_surfaces.isEmpty())
+ m_surfaceId = 1;
+
QJNIEnvironmentPrivate env;
if (!env)
return;
diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp
index f27bea8863..2c6e8370ce 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp
@@ -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()
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
index f0c4a1de2a..d14426d595 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
@@ -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();
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.h b/src/plugins/platforms/android/qandroidplatformopenglwindow.h
index 83df15a524..713f943bc5 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.h
@@ -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);
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index af184cde02..529ae0a80d 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -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
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index cd9cf2ca71..311752c7b4 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -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();
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 558525b78c..d07573fb88 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -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
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index 764dd3ab86..91e32fa2ac 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -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);