summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mode/mode.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/mode/mode.cpp b/src/mode/mode.cpp
new file mode 100644
index 0000000..1441b56
--- /dev/null
+++ b/src/mode/mode.cpp
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: MIT */
+
+#include "drm++/mode/mode.hpp"
+#include "drm++/helper/ioctl.hpp"
+#include "drm++/helper/types.hpp"
+
+#include <cstring>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <drm.h>
+#include <drm_mode.h>
+
+using namespace drm;
+using namespace drm::mode;
+
+Resources::Resources(int fd, bool fetchModes) : m_fd(fd) {
+ drm_mode_card_res card_args{
+ .count_crtcs = 0,
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETRESOURCES, card_args);
+
+ std::vector<u32> crtc_ids(card_args.count_crtcs);
+ std::vector<u32> connector_ids(card_args.count_connectors);
+
+ card_args = {
+ .crtc_id_ptr = reinterpret_cast<u64>(crtc_ids.data()),
+ .connector_id_ptr = reinterpret_cast<u64>(connector_ids.data()),
+ .count_crtcs = static_cast<u32>(crtc_ids.size()),
+ .count_connectors = static_cast<u32>(connector_ids.size())
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETRESOURCES, card_args);
+
+ this->m_crtcs.reserve(card_args.count_crtcs);
+ for (const u32 crtc_id : crtc_ids) {
+ drm_mode_crtc args{
+ .crtc_id = static_cast<u32>(crtc_id),
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETCRTC, args);
+
+ this->m_crtcs.push_back({
+ .id = static_cast<u32>(args.crtc_id),
+ });
+ }
+
+ this->m_connectors.reserve(card_args.count_connectors);
+ for (const u32 connector_id : connector_ids) {
+ drm_mode_get_connector args{
+ .count_modes = fetchModes ? 0U : 1U,
+ .connector_id = static_cast<u32>(connector_id),
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETCONNECTOR, args);
+
+ std::vector<drm_mode_modeinfo> modes_raw(args.count_modes);
+ args = {
+ .modes_ptr = reinterpret_cast<u64>(modes_raw.data()),
+ .count_modes = static_cast<u32>(modes_raw.size()),
+ .connector_id = static_cast<u32>(connector_id),
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETCONNECTOR, args);
+
+ std::vector<ModeInfo> modes;
+ modes.reserve(modes_raw.size());
+ for (const auto& mode_raw : modes_raw) {
+ modes.push_back({
+ .resolution = { mode_raw.hdisplay, mode_raw.vdisplay },
+ .refreshRate = (mode_raw.clock * 1000.0) / (mode_raw.htotal * mode_raw.vtotal),
+ .preferred = (mode_raw.type & DRM_MODE_TYPE_PREFERRED) != 0,
+ .raw = {0},
+ });
+ std::memcpy(modes.back().raw, &mode_raw, sizeof(mode_raw)); // NOLINT (raw memory)
+ }
+
+ this->m_connectors.push_back({
+ .id = static_cast<u32>(args.connector_id),
+ .type = static_cast<ConnectorType>(args.connector_type),
+ .typeIndex = static_cast<u32>(args.connector_type_id),
+ .modes = std::move(modes),
+ .physicalSize = { args.mm_width, args.mm_height },
+ });
+ }
+
+ // Fetch planes
+ drm_mode_get_plane_res plane_args{
+ .count_planes = 0,
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETPLANERESOURCES, plane_args);
+
+ std::vector<u32> plane_ids(plane_args.count_planes);
+
+ plane_args.plane_id_ptr = reinterpret_cast<u64>(plane_ids.data());
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETPLANERESOURCES, plane_args);
+
+ this->m_planes.reserve(plane_args.count_planes);
+ for (const u32 plane_id : plane_ids) {
+ drm_mode_get_plane args{
+ .plane_id = static_cast<u32>(plane_id),
+ };
+ ioctl::perform(this->m_fd, DRM_IOCTL_MODE_GETPLANE, args);
+
+ std::vector<u32> possible_crtcs;
+ for (u32 i = 0; i < this->m_crtcs.size(); ++i) {
+ if (!(args.possible_crtcs & (1 << i)))
+ continue;
+ possible_crtcs.push_back(this->m_crtcs.at(i).id);
+ }
+
+ this->m_planes.push_back({
+ .id = static_cast<u32>(args.plane_id),
+ .crtcs = std::vector<u32>(possible_crtcs),
+ });
+ }
+}
+
+/* Enums */
+
+std::string mode::connectorTypeToString(ConnectorType type) {
+ switch (type) {
+ case ConnectorType::Unknown: return "Unknown";
+ case ConnectorType::VGA: return "VGA";
+ case ConnectorType::DVII: return "DVI-I";
+ case ConnectorType::DVID: return "DVI-D";
+ case ConnectorType::DVIA: return "DVI-A";
+ case ConnectorType::Composite: return "Composite";
+ case ConnectorType::SVIDEO: return "SVIDEO";
+ case ConnectorType::LVDS: return "LVDS";
+ case ConnectorType::Component: return "Component";
+ case ConnectorType::NPinDIN: return "DIN";
+ case ConnectorType::DisplayPort: return "DP";
+ case ConnectorType::HDMI_A: return "HDMI-A";
+ case ConnectorType::HDMI_B: return "HDMI-B";
+ case ConnectorType::TV: return "TV";
+ case ConnectorType::eDP: return "eDP";
+ case ConnectorType::Virtual: return "Virtual";
+ case ConnectorType::DSI: return "DSI";
+ case ConnectorType::DPI: return "DPI";
+ case ConnectorType::Writeback: return "Writeback";
+ case ConnectorType::SPI: return "SPI";
+ case ConnectorType::USB: return "USB";
+ }
+}