uikit: Deliver update requests via CADisplayLink callback

Improves performance over the default timer-implementation, and allows
us to control the rate and paused state of the display link.

Change-Id: I05761b6eb48f5e91af35735e2faa477427cd8440
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Tor Arne Vestbø 2016-06-01 13:29:28 +02:00 committed by Tor Arne Vestbø
parent fc1092cfad
commit 0b6adbcd23
4 changed files with 70 additions and 0 deletions

View File

@ -65,9 +65,13 @@ public:
UIScreen *uiScreen() const;
UIWindow *uiWindow() const;
void setUpdatesPaused(bool);
void updateProperties();
private:
void deliverUpdateRequests() const;
UIScreen *m_uiScreen;
UIWindow *m_uiWindow;
QRect m_geometry;
@ -76,6 +80,7 @@ private:
uint m_physicalDpi;
QSizeF m_physicalSize;
QIOSOrientationListener *m_orientationListener;
CADisplayLink *m_displayLink;
};
QT_END_NAMESPACE

View File

@ -40,8 +40,31 @@
#include "qiosviewcontroller.h"
#include "quiview.h"
#include <QtGui/private/qwindow_p.h>
#include <sys/sysctl.h>
// -------------------------------------------------------------------------
typedef void (^DisplayLinkBlock)(CADisplayLink *displayLink);
@implementation UIScreen (DisplayLinkBlock)
- (CADisplayLink*)displayLinkWithBlock:(DisplayLinkBlock)block
{
return [self displayLinkWithTarget:[[block copy] autorelease]
selector:@selector(invokeDisplayLinkBlock:)];
}
@end
@implementation NSObject (DisplayLinkBlock)
- (void)invokeDisplayLinkBlock:(CADisplayLink *)sender
{
DisplayLinkBlock block = static_cast<id>(self);
block(sender);
}
@end
// -------------------------------------------------------------------------
static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
@ -208,10 +231,16 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
}
updateProperties();
m_displayLink = [m_uiScreen displayLinkWithBlock:^(CADisplayLink *) { deliverUpdateRequests(); }];
m_displayLink.paused = YES; // Enabled when clients call QWindow::requestUpdate()
[m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
QIOSScreen::~QIOSScreen()
{
[m_displayLink invalidate];
[m_orientationListener release];
[m_uiWindow release];
}
@ -291,6 +320,35 @@ void QIOSScreen::updateProperties()
QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry, m_availableGeometry);
}
void QIOSScreen::setUpdatesPaused(bool paused)
{
m_displayLink.paused = paused;
}
void QIOSScreen::deliverUpdateRequests() const
{
bool pauseUpdates = true;
QList<QWindow*> windows = QGuiApplication::allWindows();
for (int i = 0; i < windows.size(); ++i) {
if (platformScreenForWindow(windows.at(i)) != this)
continue;
QWindowPrivate *wp = static_cast<QWindowPrivate *>(QObjectPrivate::get(windows.at(i)));
if (!wp->updateRequestPending)
continue;
wp->deliverUpdateRequest();
// Another update request was triggered, keep the display link running
if (wp->updateRequestPending)
pauseUpdates = false;
}
// Pause the display link if there are no pending update requests
m_displayLink.paused = pauseUpdates;
}
QRect QIOSScreen::geometry() const
{
return m_geometry;

View File

@ -82,6 +82,8 @@ public:
QSurfaceFormat format() const Q_DECL_OVERRIDE;
void requestUpdate() Q_DECL_OVERRIDE;
private:
void applicationStateChanged(Qt::ApplicationState state);
void applyGeometry(const QRect &rect);

View File

@ -371,6 +371,11 @@ void QIOSWindow::clearAccessibleCache()
[m_view clearAccessibleCache];
}
void QIOSWindow::requestUpdate()
{
static_cast<QIOSScreen *>(screen())->setUpdatesPaused(false);
}
#include "moc_qioswindow.cpp"
QT_END_NAMESPACE