libkms: add 'ilace' param for Connector::get_mode()
[android/external-libkmsxx.git] / libkms++ / connector.cpp
1 #include <stdio.h>
2 #include <iostream>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <cassert>
7 #include "kms++.h"
8 #include "helpers.h"
10 using namespace std;
12 namespace kms
13 {
16 static const map<int, string> connector_names = {
17         { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
18         { DRM_MODE_CONNECTOR_VGA, "VGA" },
19         { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
20         { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
21         { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
22         { DRM_MODE_CONNECTOR_Composite, "Composite" },
23         { DRM_MODE_CONNECTOR_SVIDEO, "S-Video" },
24         { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
25         { DRM_MODE_CONNECTOR_Component, "Component" },
26         { DRM_MODE_CONNECTOR_9PinDIN, "9-Pin-DIN" },
27         { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
28         { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
29         { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
30         { DRM_MODE_CONNECTOR_TV, "TV" },
31         { DRM_MODE_CONNECTOR_eDP, "eDP" },
32         { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
33         { DRM_MODE_CONNECTOR_DSI, "DSI" },
34 };
36 static const map<int, string> connection_str = {
37         { 0, "<unknown>" },
38         { DRM_MODE_CONNECTED, "Connected" },
39         { DRM_MODE_DISCONNECTED, "Disconnected" },
40         { DRM_MODE_UNKNOWNCONNECTION, "Unknown" },
41 };
43 static const map<int, string> subpix_str = {
44 #define DEF_SUBPIX(c) { DRM_MODE_SUBPIXEL_##c, #c }
45         DEF_SUBPIX(UNKNOWN),
46         DEF_SUBPIX(HORIZONTAL_RGB),
47         DEF_SUBPIX(HORIZONTAL_BGR),
48         DEF_SUBPIX(VERTICAL_RGB),
49         DEF_SUBPIX(VERTICAL_BGR),
50         DEF_SUBPIX(NONE),
51 #undef DEF_SUBPIX
52 };
54 struct ConnectorPriv
55 {
56         drmModeConnectorPtr drm_connector;
57 };
59 Connector::Connector(Card &card, uint32_t id, uint32_t idx)
60         :DrmObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx)
61 {
62         m_priv = new ConnectorPriv();
64         m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
65         assert(m_priv->drm_connector);
67         const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
68         m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id);
69 }
72 Connector::~Connector()
73 {
74         drmModeFreeConnector(m_priv->drm_connector);
75         delete m_priv;
76 }
78 void Connector::setup()
79 {
80         if (m_priv->drm_connector->encoder_id != 0)
81                 m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id);
82         else
83                 m_current_encoder = 0;
85         if (m_current_encoder)
86                 m_saved_crtc = m_current_encoder->get_crtc();
87         else
88                 m_saved_crtc = 0;
89 }
91 void Connector::restore_mode()
92 {
93         if (m_saved_crtc)
94                 m_saved_crtc->restore_mode(this);
95 }
97 Videomode Connector::get_default_mode() const
98 {
99         drmModeModeInfo drmmode = m_priv->drm_connector->modes[0];
101         return drm_mode_to_video_mode(drmmode);
104 Videomode Connector::get_mode(const string& mode) const
106         auto c = m_priv->drm_connector;
108         for (int i = 0; i < c->count_modes; i++)
109                 if (mode == c->modes[i].name)
110                         return drm_mode_to_video_mode(c->modes[i]);
112         throw invalid_argument(mode + ": mode not found");
115 Videomode Connector::get_mode(unsigned xres, unsigned yres, unsigned refresh, bool ilace) const
117         auto c = m_priv->drm_connector;
119         for (int i = 0; i < c->count_modes; i++) {
120                 drmModeModeInfo& m = c->modes[i];
122                 if (m.hdisplay != xres || m.vdisplay != yres)
123                         continue;
125                 if (refresh && m.vrefresh != refresh)
126                         continue;
128                 if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE))
129                         continue;
131                 return drm_mode_to_video_mode(c->modes[i]);
132         }
134         throw invalid_argument("mode not found");
137 bool Connector::connected() const
139         return m_priv->drm_connector->connection == DRM_MODE_CONNECTED ||
140                         m_priv->drm_connector->connection == DRM_MODE_UNKNOWNCONNECTION;
143 vector<Crtc*> Connector::get_possible_crtcs() const
145         vector<Crtc*> crtcs;
147         for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) {
148                 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
150                 auto l = enc->get_possible_crtcs();
152                 crtcs.insert(crtcs.end(), l.begin(), l.end());
153         }
155         return crtcs;
158 Crtc* Connector::get_current_crtc() const
160         if (m_current_encoder)
161                 return m_current_encoder->get_crtc();
162         else
163                 return 0;
166 uint32_t Connector::connector_type() const
168         return m_priv->drm_connector->connector_type;
171 uint32_t Connector::connector_type_id() const
173         return m_priv->drm_connector->connector_type_id;
176 uint32_t Connector::mmWidth() const
178         return m_priv->drm_connector->mmWidth;
181 uint32_t Connector::mmHeight() const
183         return m_priv->drm_connector->mmHeight;
186 uint32_t Connector::subpixel() const
188         return m_priv->drm_connector->subpixel;
191 const string& Connector::subpixel_str() const
193         return subpix_str.at(subpixel());
196 std::vector<Videomode> Connector::get_modes() const
198         vector<Videomode> modes;
200         for (int i = 0; i < m_priv->drm_connector->count_modes; i++)
201                 modes.push_back(drm_mode_to_video_mode(
202                                         m_priv->drm_connector->modes[i]));
204         return modes;
207 std::vector<Encoder*> Connector::get_encoders() const
209         vector<Encoder*> encoders;
211         for (int i = 0; i < m_priv->drm_connector->count_encoders; i++) {
212                 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
213                 encoders.push_back(enc);
214         }
215         return encoders;