Merge lp:~gerboland/qtubuntu/surface-visible-hidden-side-channel into lp:qtubuntu

Proposed by kevin gunn
Status: Merged
Merged at revision: 219
Proposed branch: lp:~gerboland/qtubuntu/surface-visible-hidden-side-channel
Merge into: lp:qtubuntu
Diff against target: 135 lines (+54/-5)
3 files modified
src/platforms/ubuntu/ubuntucommon/integration.cc (+10/-1)
src/platforms/ubuntu/ubuntucommon/window.cc (+40/-4)
src/platforms/ubuntu/ubuntucommon/window.h (+4/-0)
To merge this branch: bzr merge lp:~gerboland/qtubuntu/surface-visible-hidden-side-channel
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Ubuntu Phablet Team Pending
Review via email: mp+215884@code.launchpad.net

Commit message

Lifecycle events emit expose events to safely stop & resume the renderer threads.

We don't use hide/show directly as hide causes Qt to stop the renderer, but then release the GL context and its resources. Expose events just stop & resume the renderer without altering the context.

Description of the change

The Qt5.2 blocking at eglSwapBuffers fix is to never block, but to stop clients rendering continually, we use a side-channel to notify clients that their surfaces are hidden and they can stop rendering, and when they can resume.

 * Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes)
Y
 * Did you build your software in a clean sbuild/pbuilder chroot or ppa?
Y
 * Did you build your software in a clean sbuild/pbuilder armhf chroot or ppa?
Y
 * Has a 5 minute exploratory testing run been executed on N4?
Y
 * If you changed the packaging (debian), did you subscribe a core-dev to this MP?
N/A
 * What components might get impacted by your changes?
Any app that renders
 * Have you requested review by the teams of these owning components?
No, this is very low level component shared with all Qt apps on touch, so if one is broken, all would be.

To post a comment you must log in.
Revision history for this message
Gerry Boland (gerboland) wrote :

To test, fetch this file and save on the device:
http://people.canonical.com/~gerboland/dateTime.qml
Run it with this command (with shell unlocked):

QSG_RENDER_TIMING=1 qmlscene dateTime.qml
--desktop_file_hint=/usr/share/applications/address-book-app.desktop

You should see the time printed on screen, and being printed on your
console once per second. You'll also see rendering statistics once per frame.

Now hit your power key. You should see that the render statistics stop,
yet you still get the time printed on your console. (note lifecycle
doesn't apply to manually started apps).

Hit the power key again, and unlock the greeter. Rendering should resume
immediately.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
221. By Gerry Boland

Using the hide/show events at all is dangerous, rely solely on expose

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/platforms/ubuntu/ubuntucommon/integration.cc'
2--- src/platforms/ubuntu/ubuntucommon/integration.cc 2013-10-14 09:55:36 +0000
3+++ src/platforms/ubuntu/ubuntucommon/integration.cc 2014-04-16 16:30:46 +0000
4@@ -19,7 +19,7 @@
5 #include "clipboard.h"
6 #include "input_adaptor_factory.h"
7 #include "base/logging.h"
8-#include <QtCore/QCoreApplication>
9+#include <QGuiApplication>
10 #include <qpa/qplatformnativeinterface.h>
11 #include <qpa/qplatforminputcontextfactory_p.h>
12 #include <qpa/qplatforminputcontext.h>
13@@ -35,6 +35,10 @@
14 QUbuntuIntegration* integration = static_cast<QUbuntuIntegration*>(context);
15 integration->screen()->toggleSensors(true);
16 QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::ApplicationActivate));
17+
18+ Q_FOREACH(QWindow *window, QGuiApplication::allWindows()) {
19+ QGuiApplication::postEvent(window, new QExposeEvent( window->geometry() ));
20+ }
21 }
22
23 static void aboutToStopCallback(UApplicationArchive *archive, void* context) {
24@@ -43,6 +47,11 @@
25 QUbuntuIntegration* integration = static_cast<QUbuntuIntegration*>(context);
26 integration->screen()->toggleSensors(false);
27 integration->inputContext()->hideInputPanel();
28+
29+ Q_FOREACH(QWindow *window, QGuiApplication::allWindows()) {
30+ QGuiApplication::postEvent(window, new QExposeEvent( QRegion() ));
31+ }
32+
33 QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::ApplicationDeactivate));
34 }
35
36
37=== modified file 'src/platforms/ubuntu/ubuntucommon/window.cc'
38--- src/platforms/ubuntu/ubuntucommon/window.cc 2013-12-11 04:32:09 +0000
39+++ src/platforms/ubuntu/ubuntucommon/window.cc 2014-04-16 16:30:46 +0000
40@@ -24,6 +24,7 @@
41 #include "base/logging.h"
42 #include <qpa/qwindowsysteminterface.h>
43 #include <ubuntu/application/ui/window.h>
44+#include <QRegion>
45
46 static void eventCallback(void* context, const Event* event) {
47 DLOG("eventCallback (context=%p, event=%p)", context, event);
48@@ -41,7 +42,9 @@
49 , systemSession_(systemSession)
50 , uainstance_(instance)
51 , screen_(screen)
52- , isShell_(isShell) {
53+ , isShell_(isShell)
54+ , exposed_(false)
55+{
56 if (!systemSession) {
57 // Non-system sessions can't resize the window geometry.
58 geometry_ = screen->availableGeometry();
59@@ -183,12 +186,45 @@
60 void QUbuntuWindow::setVisible(bool visible) {
61 DLOG("QUbuntuWindow::setVisible (this=%p, visible=%s)", this, visible ? "true" : "false");
62 if (isShell_ == false)
63- screen_->toggleSensors(visible);
64+ screen_->toggleSensors(visible);
65+
66+ setExposed(visible);
67
68 if (visible) {
69 ua_ui_window_show(window_);
70+ } else {
71+ ua_ui_window_hide(window_);
72+ }
73+}
74+
75+bool QUbuntuWindow::isExposed() const {
76+ return exposed_;
77+}
78+
79+void QUbuntuWindow::setExposed(const bool exposed) {
80+ DLOG("QUbuntuWindow::setExposed (this=%p, exposed=%s)", this, exposed ? "true" : "false");
81+
82+ if (exposed_ == exposed)
83+ return;
84+
85+ exposed_ = exposed;
86+ if (exposed_) {
87+ QWindowSystemInterface::handleExposeEvent(window(), geometry());
88+ } else {
89 QWindowSystemInterface::handleExposeEvent(window(), QRect());
90- } else {
91- ua_ui_window_hide(window_);
92+ }
93+}
94+
95+void QUbuntuWindow::windowEvent(QEvent *event) {
96+ if (event->type() == QEvent::Expose) {
97+ QRegion region = static_cast<QExposeEvent *>(event)->region();
98+
99+ if (region.isEmpty()) {
100+ // hiding window causes Qt to release the GL context and its resources, which is a bit severe
101+ // Instead can use the exposure system to stop the rendering loop, but hold onto the resources
102+ setExposed(false);
103+ } else {
104+ setExposed(true);
105+ }
106 }
107 }
108
109=== modified file 'src/platforms/ubuntu/ubuntucommon/window.h'
110--- src/platforms/ubuntu/ubuntucommon/window.h 2013-08-02 21:32:00 +0000
111+++ src/platforms/ubuntu/ubuntucommon/window.h 2014-04-16 16:30:46 +0000
112@@ -34,12 +34,15 @@
113 void setGeometry(const QRect&);
114 void setWindowState(Qt::WindowState state);
115 void setVisible(bool visible);
116+ bool isExposed() const;
117+ void windowEvent(QEvent *event);
118
119 QUbuntuInput* input_;
120
121 private:
122 void createWindow();
123 void moveResize(const QRect& rect);
124+ void setExposed(const bool exposed);
125
126 UAUiWindow* window_;
127 Qt::WindowState state_;
128@@ -49,6 +52,7 @@
129 UAUiWindowProperties* wprops_;
130 QUbuntuScreen* screen_;
131 bool isShell_;
132+ bool exposed_;
133 };
134
135 #endif // QUBUNTUWINDOW_H

Subscribers

People subscribed via source and target branches