Commit d07c3705 authored by Roman Kovalivskyi's avatar Roman Kovalivskyi
Browse files

drm_hwcomposer: Add property hwc.drm.primary_display_order



There are cases when primary display lookup order should be
overriden. This could be achieved with adding system property
hwc.drm.primary_display_order.

Example of primary_display_order property usage:
hwc.drm.primary_display_order=HDMI-A-2,HDMI-A-1,...

This means that first priority goes to HDMI-A-2 connector, then
HDMI-A-1 connector, then everything else. Internal connectors have
higher priority than any other connectors not mentioned in property.

Connected connector with highest priority would be selected as a
primary display.

Signed-off-by: Roman Kovalivskyi's avatarRoman Kovalivskyi <roman.kovalivskyi@globallogic.com>
parent df882994
......@@ -30,11 +30,91 @@
#include <xf86drmMode.h>
#include <cinttypes>
#include <algorithm>
#include <array>
#include <string>
#include <cutils/properties.h>
#include <log/log.h>
static void trim_left(std::string &str) {
str.erase(std::begin(str),
std::find_if(std::begin(str), std::end(str),
[](int ch) { return !std::isspace(ch); }));
}
static void trim_right(std::string &str) {
str.erase(std::find_if(std::rbegin(str), std::rend(str),
[](int ch) { return !std::isspace(ch); })
.base(),
std::end(str));
}
static void trim(std::string &str) {
trim_left(str);
trim_right(str);
}
namespace android {
static std::vector<std::string> read_primary_display_order_prop() {
std::array<char, PROPERTY_VALUE_MAX> display_order_buf;
property_get("hwc.drm.primary_display_order", display_order_buf.data(),
"...");
std::vector<std::string> display_order;
std::istringstream str(display_order_buf.data());
for (std::string conn_name = ""; std::getline(str, conn_name, ',');) {
trim(conn_name);
display_order.push_back(std::move(conn_name));
}
return display_order;
}
static std::vector<DrmConnector *> make_primary_display_candidates(
std::vector<std::unique_ptr<DrmConnector>> &connectors) {
std::vector<DrmConnector *> primary_candidates;
std::transform(std::begin(connectors), std::end(connectors),
std::back_inserter(primary_candidates),
[](std::unique_ptr<DrmConnector> &conn) {
return conn.get();
});
primary_candidates.erase(std::remove_if(std::begin(primary_candidates),
std::end(primary_candidates),
[](const DrmConnector *conn) {
return conn->state() !=
DRM_MODE_CONNECTED;
}),
std::end(primary_candidates));
std::vector<std::string> display_order = read_primary_display_order_prop();
bool use_other = display_order.back() == "...";
// putting connectors from primary_display_order first
auto curr_connector = std::begin(primary_candidates);
for (const std::string &display_name : display_order) {
auto it = std::find_if(std::begin(primary_candidates),
std::end(primary_candidates),
[&display_name](const DrmConnector *conn) {
return conn->name() == display_name;
});
if (it != std::end(primary_candidates)) {
std::iter_swap(it, curr_connector);
++curr_connector;
}
}
if (use_other) {
// then putting internal connectors second, everything else afterwards
std::partition(curr_connector, std::end(primary_candidates),
[](const DrmConnector *conn) { return conn->internal(); });
} else {
primary_candidates.erase(curr_connector, std::end(primary_candidates));
}
return primary_candidates;
}
DrmDevice::DrmDevice() : event_listener_(this) {
}
......@@ -173,19 +253,26 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) {
connectors_.emplace_back(std::move(conn));
}
// First look for primary amongst internal connectors
for (auto &conn : connectors_) {
if (conn->internal() && !found_primary) {
conn->set_display(num_displays);
displays_[num_displays] = num_displays;
++num_displays;
found_primary = true;
break;
}
// Primary display priority:
// 1) hwc.drm.primary_display_order property
// 2) internal connectors
// 3) anything else
std::vector<DrmConnector *>
primary_candidates = make_primary_display_candidates(connectors_);
if (!primary_candidates.empty() && !found_primary) {
DrmConnector &conn = **std::begin(primary_candidates);
conn.set_display(num_displays);
displays_[num_displays] = num_displays;
++num_displays;
found_primary = true;
} else {
ALOGE(
"Failed to find primary display from \"hwc.drm.primary_display_order\" "
"property");
}
// Then pick first available as primary and for the others assign
// consecutive display_numbers.
// If no priority display were found then pick first available as primary and
// for the others assign consecutive display_numbers.
for (auto &conn : connectors_) {
if (conn->external() || conn->internal()) {
if (!found_primary) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment