Initial version
[android/external-libkmsxx.git] / libkms++ / card.cpp
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <utility>
5 #include <stdexcept>
6 #include <string.h>
8 #include <xf86drm.h>
9 #include <xf86drmMode.h>
11 #include "kms++.h"
13 #ifndef DRM_CLIENT_CAP_ATOMIC
14 #define DRM_CLIENT_CAP_ATOMIC 3
15 #endif
17 namespace kms
18 {
20 Card::Card()
21 {
22         const char *card = "/dev/dri/card0";
24         int fd = open(card, O_RDWR | O_CLOEXEC);
25         if (fd < 0)
26                 throw std::invalid_argument("foo");
27         m_fd = fd;
29         int r;
31         r = drmSetMaster(fd);
32         m_master = r == 0;
34         r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
35         if (r)
36                 throw std::invalid_argument("foo");
38         r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1);
39         m_has_atomic = r == 0;
41         uint64_t has_dumb;
42         r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
43         if (r || !has_dumb)
44                 throw std::invalid_argument("foo");
46         auto res = drmModeGetResources(m_fd);
47         if (!res)
48                 throw std::invalid_argument("foo");
50         for (int i = 0; i < res->count_connectors; ++i) {
51                 uint32_t id = res->connectors[i];
52                 m_obmap[id] = new Connector(*this, id, i);
53         }
55         for (int i = 0; i < res->count_crtcs; ++i) {
56                 uint32_t id = res->crtcs[i];
57                 m_obmap[id] = new Crtc(*this, id, i);
58         }
60         for (int i = 0; i < res->count_encoders; ++i) {
61                 uint32_t id = res->encoders[i];
62                 m_obmap[id] = new Encoder(*this, id);
63         }
65         drmModeFreeResources(res);
67         auto planeRes = drmModeGetPlaneResources(m_fd);
69         for (uint i = 0; i < planeRes->count_planes; ++i) {
70                 uint32_t id = planeRes->planes[i];
71                 m_obmap[id] = new Plane(*this, id);
72         }
74         drmModeFreePlaneResources(planeRes);
76         // collect all possible props
77         for (auto ob : get_objects()) {
78                 auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type());
80                 if (props == nullptr)
81                         continue;
83                 for (unsigned i = 0; i < props->count_props; ++i) {
84                         uint32_t prop_id = props->props[i];
86                         if (m_obmap.find(prop_id) == m_obmap.end())
87                                 m_obmap[prop_id] = new Property(*this, prop_id);
88                 }
90                 drmModeFreeObjectProperties(props);
91         }
93         for (auto pair : m_obmap)
94                 pair.second->setup();
95 }
97 Card::~Card()
98 {
99         for (auto pair : m_obmap)
100                 delete pair.second;
102         close(m_fd);
105 template <class T> static void print_obs(const std::map<uint32_t, DrmObject*>& obmap)
107         for (auto pair : obmap) {
108                 auto ob = pair.second;
109                 if (dynamic_cast<T*>(ob)) {
110                         ob->print_short();
111                         //ob->print_props();
112                 }
113         }
116 void Card::print_short() const
118         print_obs<Connector>(m_obmap);
119         print_obs<Encoder>(m_obmap);
120         print_obs<Crtc>(m_obmap);
121         print_obs<Plane>(m_obmap);
124 Property* Card::get_prop(const char *name) const
126         for (auto pair : m_obmap) {
127                 auto prop = dynamic_cast<Property*>(pair.second);
128                 if (!prop)
129                         continue;
131                 if (strcmp(name, prop->name()) == 0)
132                         return prop;
133         }
135         throw std::invalid_argument("foo");
138 Connector* Card::get_first_connected_connector() const
140         for(auto pair : m_obmap) {
141                 auto c = dynamic_cast<Connector*>(pair.second);
143                 if (c && c->connected())
144                         return c;
145         }
147         throw std::invalid_argument("no connected connectors");
150 DrmObject* Card::get_object(uint32_t id) const
152         return m_obmap.at(id);
155 std::vector<Connector*> Card::get_connectors() const
157         std::vector<Connector*> v;
158         for(auto pair : m_obmap) {
159                 auto p = dynamic_cast<Connector*>(pair.second);
160                 if (p)
161                         v.push_back(p);
162         }
163         return v;
166 std::vector<Plane*> Card::get_planes() const
168         std::vector<Plane*> v;
169         for(auto pair : m_obmap) {
170                 auto p = dynamic_cast<Plane*>(pair.second);
171                 if (p)
172                         v.push_back(p);
173         }
174         return v;
177 std::vector<DrmObject*> Card::get_objects() const
179         std::vector<DrmObject*> v;
180         for(auto pair : m_obmap)
181                 v.push_back(pair.second);
182         return v;
185 Crtc* Card::get_crtc_by_index(uint32_t idx) const
187         for(auto pair : m_obmap) {
188                 auto crtc = dynamic_cast<Crtc*>(pair.second);
189                 if (crtc && crtc->idx() == idx)
190                         return crtc;
191         }
192         throw std::invalid_argument("fob");
195 Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast<Crtc*>(get_object(id)); }
196 Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast<Encoder*>(get_object(id)); }
197 Property* Card::get_prop(uint32_t id) const { return dynamic_cast<Property*>(get_object(id)); }