diff options
| author | PancakeTAS <pancake@mgnet.work> | 2026-07-06 22:34:07 +0200 |
|---|---|---|
| committer | PancakeTAS <pancake@mgnet.work> | 2026-07-06 22:34:07 +0200 |
| commit | 818db23b28f0e390aff0f225d1dad69779364a40 (patch) | |
| tree | b82bab590b8cbc4325eb70ba3119ef8fc09ff2fa /src | |
| parent | Implement framebuffer object (diff) | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/mode/mode.cpp | 142 |
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"; + } +} |
