blob: c4bf7f86a7e9d188ff5435067150149641635724 [file] [log] [blame]
#include <kms++util/resourcemanager.h>
#include <algorithm>
#include <kms++util/strhelpers.h>
using namespace kms;
using namespace std;
template<class C, class T>
auto contains(const C& v, const T& x)
-> decltype(end(v), true)
{
return end(v) != std::find(begin(v), end(v), x);
}
ResourceManager::ResourceManager(Card& card)
: m_card(card)
{
}
void ResourceManager::reset()
{
m_reserved_connectors.clear();
m_reserved_crtcs.clear();
m_reserved_planes.clear();
}
static Connector* find_connector(Card& card, const vector<Connector*> reserved)
{
for (Connector* conn : card.get_connectors()) {
if (!conn->connected())
continue;
if (contains(reserved, conn))
continue;
return conn;
}
return nullptr;
}
static Connector* resolve_connector(Card& card, const string& name, const vector<Connector*> reserved)
{
auto connectors = card.get_connectors();
if (name[0] == '@') {
char* endptr;
unsigned id = strtoul(name.c_str() + 1, &endptr, 10);
if (*endptr == 0) {
Connector* c = card.get_connector(id);
if (!c || contains(reserved, c))
return nullptr;
return c;
}
} else {
char* endptr;
unsigned idx = strtoul(name.c_str(), &endptr, 10);
if (*endptr == 0) {
if (idx >= connectors.size())
return nullptr;
Connector* c = connectors[idx];
if (contains(reserved, c))
return nullptr;
return c;
}
}
for (Connector* conn : connectors) {
if (to_lower(conn->fullname()).find(to_lower(name)) == string::npos)
continue;
if (contains(reserved, conn))
continue;
return conn;
}
return nullptr;
}
Connector* ResourceManager::reserve_connector(const string& name)
{
Connector* conn;
if (name.empty())
conn = find_connector(m_card, m_reserved_connectors);
else
conn = resolve_connector(m_card, name, m_reserved_connectors);
if (!conn)
return nullptr;
m_reserved_connectors.push_back(conn);
return conn;
}
Connector* ResourceManager::reserve_connector(Connector* conn)
{
if (!conn)
return nullptr;
if (contains(m_reserved_connectors, conn))
return nullptr;
m_reserved_connectors.push_back(conn);
return conn;
}
Crtc* ResourceManager::reserve_crtc(Connector* conn)
{
if (!conn)
return nullptr;
if (Crtc* crtc = conn->get_current_crtc()) {
m_reserved_crtcs.push_back(crtc);
return crtc;
}
for (Crtc* crtc : conn->get_possible_crtcs()) {
if (contains(m_reserved_crtcs, crtc))
continue;
m_reserved_crtcs.push_back(crtc);
return crtc;
}
return nullptr;
}
Plane* ResourceManager::reserve_plane(Crtc* crtc, PlaneType type, PixelFormat format)
{
if (!crtc)
return nullptr;
for (Plane* plane : crtc->get_possible_planes()) {
if (plane->plane_type() != type)
continue;
if (format != PixelFormat::Undefined && !plane->supports_format(format))
continue;
if (contains(m_reserved_planes, plane))
continue;
m_reserved_planes.push_back(plane);
return plane;
}
return nullptr;
}
Plane* ResourceManager::reserve_generic_plane(Crtc* crtc, PixelFormat format)
{
if (!crtc)
return nullptr;
for (Plane* plane : crtc->get_possible_planes()) {
if (plane->plane_type() == PlaneType::Cursor)
continue;
if (format != PixelFormat::Undefined && !plane->supports_format(format))
continue;
if (contains(m_reserved_planes, plane))
continue;
m_reserved_planes.push_back(plane);
return plane;
}
return nullptr;
}
Plane* ResourceManager::reserve_primary_plane(Crtc* crtc, PixelFormat format)
{
return reserve_plane(crtc, PlaneType::Primary, format);
}
Plane* ResourceManager::reserve_overlay_plane(Crtc* crtc, PixelFormat format)
{
return reserve_plane(crtc, PlaneType::Overlay, format);
}