summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2012-05-04 13:10:41 +0200
committerQt by Nokia <qt-info@nokia.com>2012-05-08 22:30:10 +0200
commitf280efc6201adf8933c9d48a1d5b6983ee9fed9b (patch)
tree8ec0d8466b951272667d6c620959d51383902630 /src/plugins/platforms
parent4a58853aeae02677e6ee1a0f0ef8839578c32573 (diff)
Added QScreen::refreshRate() to get the vertical refresh rate.
To give applications that want it the option to use a fixed timestep for animations, and to avoid having values of 60 hard-coded (we have a couple of those in qtdeclarative/src/quick already), we need to know the refresh rates of the screens we are rendering to. Change-Id: Ife49162e830440ad7eab563a27e8aebbbafc5fc5 Reviewed-by: Girish Ramakrishnan <girish.1.ramakrishnan@nokia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com> Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h2
-rw-r--r--src/plugins/platforms/xcb/README4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp39
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp39
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h4
-rw-r--r--src/plugins/platforms/xcb/xcb.pro2
8 files changed, 96 insertions, 4 deletions
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 2476e15169..cc694fe0ea 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE
QWindowsScreenData::QWindowsScreenData() :
dpi(96, 96), depth(32), format(QImage::Format_ARGB32_Premultiplied),
- flags(VirtualDesktop), orientation(Qt::LandscapeOrientation)
+ flags(VirtualDesktop), orientation(Qt::LandscapeOrientation),
+ refreshRateHz(60)
{
}
@@ -103,6 +104,9 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
data.depth = GetDeviceCaps(hdc, BITSPIXEL);
data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
+ const int refreshRate = GetDeviceCaps(hdc, VREFRESH);
+ if (refreshRate > 1) // 0,1 means heardware default.
+ data.refreshRateHz = refreshRate;
DeleteDC(hdc);
} else {
qWarning("%s: Unable to obtain handle for monitor '%s', defaulting to %g DPI.",
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 56e9ab304e..615d4faf15 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -70,6 +70,7 @@ struct QWindowsScreenData
unsigned flags;
QString name;
Qt::ScreenOrientation orientation;
+ qreal refreshRateHz;
};
class QWindowsScreen : public QPlatformScreen
@@ -87,6 +88,7 @@ public:
virtual QImage::Format format() const { return m_data.format; }
virtual QSizeF physicalSize() const { return m_data.physicalSizeMM; }
virtual QDpi logicalDpi() const { return m_data.dpi; }
+ virtual qreal refreshRate() const { return m_data.refreshRateHz; }
virtual QString name() const { return m_data.name; }
virtual Qt::ScreenOrientation primaryOrientation() { return m_data.orientation; }
virtual QList<QPlatformScreen *> virtualSiblings() const;
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index eede0cc149..14e98b8145 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -1,8 +1,8 @@
Requires libxcb >= 1.5.
Required packages:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev
On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev
The packages for xcb-render-util can be installed manually from http://packages.ubuntu.com/natty/libxcb-render-util0 and http://packages.ubuntu.com/natty/libxcb-render-util0-dev
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 76979bf05f..728dd1dd00 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -60,6 +60,7 @@
#include <stdio.h>
#include <errno.h>
#include <xcb/xfixes.h>
+#include <xcb/randr.h>
#ifdef XCB_USE_XLIB
#include <X11/Xlib.h>
@@ -109,7 +110,9 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
, m_has_support_for_dri2(false)
#endif
, xfixes_first_event(0)
+ , xrandr_first_event(0)
, has_shape_extension(false)
+ , has_randr_extension(false)
, has_input_shape(false)
{
m_primaryScreen = 0;
@@ -160,6 +163,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
+ initializeXRandr();
+
int screenNumber = 0;
while (it.rem) {
m_screens << new QXcbScreen(this, it.data, screenNumber++);
@@ -586,6 +591,15 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp);
m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
handled = true;
+ } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
+ xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event;
+ foreach (QXcbScreen *s, m_screens) {
+ if (s->root() == change_event->root ) {
+ s->updateRefreshRate();
+ break;
+ }
+ }
+ handled = true;
}
}
@@ -1060,6 +1074,31 @@ void QXcbConnection::initializeXRender()
#endif
}
+void QXcbConnection::initializeXRandr()
+{
+ const xcb_query_extension_reply_t *xrandr_reply = xcb_get_extension_data(m_connection, &xcb_randr_id);
+ if (!xrandr_reply || !xrandr_reply->present)
+ return;
+
+ xrandr_first_event = xrandr_reply->first_event;
+
+ xcb_generic_error_t *error = 0;
+ xcb_randr_query_version_cookie_t xrandr_query_cookie = xcb_randr_query_version(m_connection,
+ XCB_RANDR_MAJOR_VERSION,
+ XCB_RANDR_MINOR_VERSION);
+
+ has_randr_extension = true;
+
+ xcb_randr_query_version_reply_t *xrandr_query = xcb_randr_query_version_reply(m_connection,
+ xrandr_query_cookie, &error);
+ if (!xrandr_query || error || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) {
+ qWarning("QXcbConnection: Failed to initialize XRandr");
+ free(error);
+ has_randr_extension = false;
+ }
+ free(xrandr_query);
+}
+
void QXcbConnection::initializeXShape()
{
const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 34943bfdef..86eaf5d7d9 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -355,6 +355,7 @@ public:
bool hasXFixes() const { return xfixes_first_event > 0; }
bool hasXShape() const { return has_shape_extension; }
+ bool hasXRandr() const { return has_randr_extension; }
bool hasInputShape() const { return has_input_shape; }
private slots:
@@ -365,6 +366,7 @@ private:
void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
void initializeXFixes();
void initializeXRender();
+ void initializeXRandr();
void initializeXShape();
#ifdef XCB_USE_DRI2
void initializeDri2();
@@ -432,8 +434,10 @@ private:
QVector<PeekFunc> m_peekFuncs;
uint32_t xfixes_first_event;
+ uint32_t xrandr_first_event;
bool has_shape_extension;
+ bool has_randr_extension;
bool has_input_shape;
};
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index ae5e4cce34..fbfaa894eb 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -48,13 +48,23 @@
#include <QDebug>
+#include <xcb/randr.h>
+
+#include <QtGui/QWindowSystemInterface>
+
QT_BEGIN_NAMESPACE
QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number)
: QXcbObject(connection)
, m_screen(screen)
, m_number(number)
+ , m_refreshRate(60)
{
+ if (connection->hasXRandr())
+ xcb_randr_select_input(xcb_connection(), screen->root, true);
+
+ updateRefreshRate();
+
#ifdef Q_XCB_DEBUG
qDebug();
qDebug("Information of screen %d:", screen->root);
@@ -63,6 +73,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
qDebug(" depth.........: %d", screen->root_depth);
qDebug(" white pixel...: %x", screen->white_pixel);
qDebug(" black pixel...: %x", screen->black_pixel);
+ qDebug(" refresh rate...: %d", m_refreshRate);
qDebug();
#endif
@@ -228,6 +239,34 @@ QPlatformCursor *QXcbScreen::cursor() const
return m_cursor;
}
+qreal QXcbScreen::refreshRate() const
+{
+ return m_refreshRate;
+}
+
+void QXcbScreen::updateRefreshRate()
+{
+ if (!connection()->hasXRandr())
+ return;
+
+ int rate = m_refreshRate;
+
+ xcb_randr_get_screen_info_reply_t *screenInfoReply =
+ xcb_randr_get_screen_info_reply(xcb_connection(), xcb_randr_get_screen_info_unchecked(xcb_connection(), m_screen->root), 0);
+
+ if (screenInfoReply) {
+ rate = screenInfoReply->rate;
+ free(screenInfoReply);
+ }
+
+ if (rate == m_refreshRate)
+ return;
+
+ m_refreshRate = rate;
+
+ QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), rate);
+}
+
int QXcbScreen::screenNumber() const
{
return m_number;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index ba3f4aff8d..7a81d8b43a 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -69,6 +69,7 @@ public:
QImage::Format format() const;
QSizeF physicalSize() const;
QPlatformCursor *cursor() const;
+ qreal refreshRate() const;
int screenNumber() const;
@@ -84,6 +85,8 @@ public:
QString name() const;
+ void updateRefreshRate();
+
private:
xcb_screen_t *m_screen;
int m_number;
@@ -92,6 +95,7 @@ private:
xcb_window_t m_clientLeader;
QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
QXcbCursor *m_cursor;
+ int m_refreshRate;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index 0da5fb1674..210b770a51 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -91,7 +91,7 @@ contains(DEFINES, XCB_USE_DRI2) {
}
}
-LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shape -lxcb-shm
+LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shape -lxcb-shm -lxcb-randr
DEFINES += $$QMAKE_DEFINES_XCB
LIBS += $$QMAKE_LIBS_XCB