From a73cead0e0ffe674d0c873a726d2535ba60d9614 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 18 Mar 2015 18:42:01 +0300 Subject: xcb: Speed up screens' initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Daniel Vrátil Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 137 +++++++++++++++------------ 1 file changed, 77 insertions(+), 60 deletions(-) (limited to 'src/plugins/platforms/xcb/qxcbconnection.cpp') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 3b3fcd0b49..5b101e66bb 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -306,71 +306,88 @@ 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. - xcb_randr_get_screen_resources_cookie_t resourcesCookie = - xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); - QScopedPointer primary( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { - qWarning("failed to get the primary output of the screen"); + // 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 resources; + xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = + xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root); + QScopedPointer 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 { - QScopedPointer resources( - xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources || error) { - qWarning("failed to get the screen resources"); - free(error); + 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_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 output( - xcb_randr_get_output_info_reply(xcb_connection(), - xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); - - // Invalid, disconnected or disabled output - if (output == NULL) - continue; - - if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { - qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); - continue; - } + 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 (output->crtc == XCB_NONE) { - qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); - continue; - } + if (outputCount) { + xcb_randr_get_output_primary_cookie_t primaryCookie = + xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); + QScopedPointer 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 { + for (int i = 0; i < outputCount; i++) { + QScopedPointer output( + xcb_randr_get_output_info_reply(xcb_connection(), + xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); + + // Invalid, disconnected or disabled output + if (output == NULL) + continue; + + if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { + qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), + xcb_randr_get_output_info_name_length(output.data())))); + continue; + } + + if (output->crtc == XCB_NONE) { + qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), + xcb_randr_get_output_info_name_length(output.data())))); + continue; + } - QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); - siblings << screen; - ++connectedOutputCount; - hasOutputs = true; - m_screens << screen; - - // There can be multiple outputs per screen, use either - // the first or an exact match. An exact match isn't - // always available if primary->output is XCB_NONE - // or currently disconnected output. - if (m_primaryScreenNumber == xcbScreenNumber) { - if (!primaryScreen || (primary && outputs[i] == primary->output)) { - if (primaryScreen) - primaryScreen->setPrimary(false); - primaryScreen = screen; - primaryScreen->setPrimary(true); - siblings.prepend(siblings.takeLast()); + QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); + siblings << screen; + ++connectedOutputCount; + hasOutputs = true; + m_screens << screen; + + // There can be multiple outputs per screen, use either + // the first or an exact match. An exact match isn't + // always available if primary->output is XCB_NONE + // or currently disconnected output. + if (m_primaryScreenNumber == xcbScreenNumber) { + if (!primaryScreen || (primary && outputs[i] == primary->output)) { + if (primaryScreen) + primaryScreen->setPrimary(false); + primaryScreen = screen; + primaryScreen->setPrimary(true); + siblings.prepend(siblings.takeLast()); + } } } } -- cgit v1.2.3