xcb: Speed up screens' initialization

Use RRGetScreenResourcesCurrent to get the screen's outputs.
It is fast but it may return nothing if the configuration is not
initialized wrt to the hardware. Call RRGetScreenResources in this
case to get the up-to-date configuration.

Task-number: QTBUG-40207
Change-Id: I84dc8a45b89d0bf8881a72b02e81f701637cdb6a
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Daniel Vrátil <dvratil@redhat.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Alexander Volkov 2015-03-18 18:42:01 +03:00 committed by Shawn Rutledge
parent f381ad63a2
commit a73cead0e0

View File

@ -306,31 +306,47 @@ void QXcbConnection::initializeScreens()
int connectedOutputCount = 0;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
xcb_randr_get_output_primary_cookie_t primaryCookie =
xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
// TODO: RRGetScreenResources has to be called on each X display at least once before
// RRGetScreenResourcesCurrent can be used - we can't know if we are the first application
// to do so or not, so we always call the slower version here. Ideally we should share some
// global flag (an atom on root window maybe) that at least other Qt apps would understand
// and could call RRGetScreenResourcesCurrent here, speeding up start.
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
// configuration is not initialized wrt to the hardware. We should call
// RRGetScreenResources in this case.
QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources;
xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root);
QScopedPointer<xcb_randr_get_screen_resources_current_reply_t, QScopedPointerPodDeleter> resources_current(
xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error));
if (!resources_current || error) {
qWarning("failed to get the current screen resources");
free(error);
} else {
xcb_timestamp_t timestamp;
xcb_randr_output_t *outputs = Q_NULLPTR;
outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
if (outputCount) {
timestamp = resources_current->config_timestamp;
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
} else {
xcb_randr_get_screen_resources_cookie_t resourcesCookie =
xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root);
resources.reset(xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error));
if (!resources || error) {
qWarning("failed to get the screen resources");
free(error);
} else {
timestamp = resources->config_timestamp;
outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data());
outputs = xcb_randr_get_screen_resources_outputs(resources.data());
}
}
if (outputCount) {
xcb_randr_get_output_primary_cookie_t primaryCookie =
xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary(
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
if (!primary || error) {
qWarning("failed to get the primary output of the screen");
free(error);
} else {
QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources(
xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error));
if (!resources || error) {
qWarning("failed to get the screen resources");
free(error);
} else {
xcb_timestamp_t timestamp = resources->config_timestamp;
outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data());
xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources.data());
for (int i = 0; i < outputCount; i++) {
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
xcb_randr_get_output_info_reply(xcb_connection(),
@ -377,6 +393,7 @@ void QXcbConnection::initializeScreens()
}
}
}
}
foreach (QPlatformScreen* s, siblings)
((QXcbScreen*)s)->setVirtualSiblings(siblings);
xcb_screen_next(&it);