1 #include <kms++util/resourcemanager.h>
2 #include <algorithm>
3 #include <kms++util/strhelpers.h>
4
5 using namespace kms;
6 using namespace std;
7
ResourceManager(Card & card)8 ResourceManager::ResourceManager(Card& card)
9 : m_card(card)
10 {
11 }
12
reset()13 void ResourceManager::reset()
14 {
15 m_reserved_connectors.clear();
16 m_reserved_crtcs.clear();
17 m_reserved_planes.clear();
18 }
19
find_connector(Card & card,const set<Connector * > reserved)20 static Connector* find_connector(Card& card, const set<Connector*> reserved)
21 {
22 for (Connector* conn : card.get_connectors()) {
23 if (!conn->connected())
24 continue;
25
26 if (reserved.count(conn))
27 continue;
28
29 return conn;
30 }
31
32 return nullptr;
33 }
34
resolve_connector(Card & card,const string & name,const set<Connector * > reserved)35 static Connector* resolve_connector(Card& card, const string& name, const set<Connector*> reserved)
36 {
37 auto connectors = card.get_connectors();
38
39 if (name[0] == '@') {
40 char* endptr;
41 unsigned id = strtoul(name.c_str() + 1, &endptr, 10);
42 if (*endptr == 0) {
43 Connector* c = card.get_connector(id);
44
45 if (!c || reserved.count(c))
46 return nullptr;
47
48 return c;
49 }
50 } else {
51 char* endptr;
52 unsigned idx = strtoul(name.c_str(), &endptr, 10);
53 if (*endptr == 0) {
54 if (idx >= connectors.size())
55 return nullptr;
56
57 Connector* c = connectors[idx];
58
59 if (reserved.count(c))
60 return nullptr;
61
62 return c;
63 }
64 }
65
66 for (Connector* conn : connectors) {
67 if (to_lower(conn->fullname()).find(to_lower(name)) == string::npos)
68 continue;
69
70 if (reserved.count(conn))
71 continue;
72
73 return conn;
74 }
75
76 return nullptr;
77 }
78
reserve_connector(const string & name)79 Connector* ResourceManager::reserve_connector(const string& name)
80 {
81 Connector* conn;
82
83 if (name.empty())
84 conn = find_connector(m_card, m_reserved_connectors);
85 else
86 conn = resolve_connector(m_card, name, m_reserved_connectors);
87
88 if (!conn)
89 return nullptr;
90
91 m_reserved_connectors.insert(conn);
92 return conn;
93 }
94
reserve_connector(Connector * conn)95 Connector* ResourceManager::reserve_connector(Connector* conn)
96 {
97 if (!conn)
98 return nullptr;
99
100 if (m_reserved_connectors.count(conn))
101 return nullptr;
102
103 m_reserved_connectors.insert(conn);
104 return conn;
105 }
106
release_connector(Connector * conn)107 void ResourceManager::release_connector(Connector* conn)
108 {
109 m_reserved_connectors.erase(conn);
110 }
111
reserve_crtc(Connector * conn)112 Crtc* ResourceManager::reserve_crtc(Connector* conn)
113 {
114 if (!conn)
115 return nullptr;
116
117 if (Crtc* crtc = conn->get_current_crtc()) {
118 m_reserved_crtcs.insert(crtc);
119 return crtc;
120 }
121
122 for (Crtc* crtc : conn->get_possible_crtcs()) {
123 if (m_reserved_crtcs.count(crtc))
124 continue;
125
126 m_reserved_crtcs.insert(crtc);
127 return crtc;
128 }
129
130 return nullptr;
131 }
132
reserve_crtc(Crtc * crtc)133 Crtc* ResourceManager::reserve_crtc(Crtc* crtc)
134 {
135 if (!crtc)
136 return nullptr;
137
138 if (m_reserved_crtcs.count(crtc))
139 return nullptr;
140
141 m_reserved_crtcs.insert(crtc);
142
143 return crtc;
144 }
145
release_crtc(Crtc * crtc)146 void ResourceManager::release_crtc(Crtc* crtc)
147 {
148 m_reserved_crtcs.erase(crtc);
149 }
150
reserve_plane(Crtc * crtc,PlaneType type,PixelFormat format)151 Plane* ResourceManager::reserve_plane(Crtc* crtc, PlaneType type, PixelFormat format)
152 {
153 if (!crtc)
154 return nullptr;
155
156 for (Plane* plane : crtc->get_possible_planes()) {
157 if (plane->plane_type() != type)
158 continue;
159
160 if (format != PixelFormat::Undefined && !plane->supports_format(format))
161 continue;
162
163 if (m_reserved_planes.count(plane))
164 continue;
165
166 m_reserved_planes.insert(plane);
167 return plane;
168 }
169
170 return nullptr;
171 }
172
reserve_plane(Plane * plane)173 Plane* ResourceManager::reserve_plane(Plane* plane)
174 {
175 if (!plane)
176 return nullptr;
177
178 if (m_reserved_planes.count(plane))
179 return nullptr;
180
181 m_reserved_planes.insert(plane);
182
183 return plane;
184 }
185
reserve_generic_plane(Crtc * crtc,PixelFormat format)186 Plane* ResourceManager::reserve_generic_plane(Crtc* crtc, PixelFormat format)
187 {
188 if (!crtc)
189 return nullptr;
190
191 for (Plane* plane : crtc->get_possible_planes()) {
192 if (plane->plane_type() == PlaneType::Cursor)
193 continue;
194
195 if (format != PixelFormat::Undefined && !plane->supports_format(format))
196 continue;
197
198 if (m_reserved_planes.count(plane))
199 continue;
200
201 m_reserved_planes.insert(plane);
202 return plane;
203 }
204
205 return nullptr;
206 }
207
reserve_primary_plane(Crtc * crtc,PixelFormat format)208 Plane* ResourceManager::reserve_primary_plane(Crtc* crtc, PixelFormat format)
209 {
210 return reserve_plane(crtc, PlaneType::Primary, format);
211 }
212
reserve_overlay_plane(Crtc * crtc,PixelFormat format)213 Plane* ResourceManager::reserve_overlay_plane(Crtc* crtc, PixelFormat format)
214 {
215 return reserve_plane(crtc, PlaneType::Overlay, format);
216 }
217
release_plane(Plane * plane)218 void ResourceManager::release_plane(Plane* plane)
219 {
220 m_reserved_planes.erase(plane);
221 }
222