diff options
| author | PancakeTAS <pancake@mgnet.work> | 2026-07-03 16:15:45 +0200 |
|---|---|---|
| committer | PancakeTAS <pancake@mgnet.work> | 2026-07-03 16:30:05 +0200 |
| commit | 5dea03465384a91466c293e55deabd0817c7e0bd (patch) | |
| tree | 7e884acb1bba09fc86487f76ea06e7e1c22781cc /src/mode/framebuffer.cpp | |
| parent | Implement version ioctl and expand comments (diff) | |
Implement framebuffer object
Diffstat (limited to 'src/mode/framebuffer.cpp')
| -rw-r--r-- | src/mode/framebuffer.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/mode/framebuffer.cpp b/src/mode/framebuffer.cpp new file mode 100644 index 0000000..46b98d1 --- /dev/null +++ b/src/mode/framebuffer.cpp @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: MIT */ + +#include "drm++/mode/framebuffer.hpp" +#include "drm++/gem.hpp" +#include "drm++/helper/ioctl.hpp" +#include "drm++/helper/types.hpp" + +#include <cassert> +#include <cstddef> +#include <optional> +#include <stdexcept> +#include <utility> +#include <vector> + +#include <drm.h> +#include <drm_mode.h> + +using namespace drm; +using namespace drm::mode; + +Framebuffer::Framebuffer( + int fd, + u32 width, + u32 height, + u32 format, + std::vector<ref<const gem::Object>> planes, + std::vector<std::pair<u32, u32>> alignments, + std::optional<u64> modifier, + bool interlaced) : m_fd(fd), + m_width(width), m_height(height), m_format(format), + m_alignments(alignments), m_modifier(modifier), m_interlaced(interlaced +) { + if (planes.empty() || planes.size() > 4 || planes.size() != alignments.size()) { + throw std::invalid_argument("invalid number of planes"); + } + + drm_mode_fb_cmd2 args{ + .width = width, + .height = height, + .pixel_format = format, + .flags = (modifier.has_value() ? DRM_MODE_FB_MODIFIERS : 0U) + | (interlaced ? DRM_MODE_FB_INTERLACED : 0U) + }; + for (size_t i = 0; i < planes.size(); ++i) { + args.handles[i] = planes.at(i).get().handle(); + args.offsets[i] = alignments.at(i).first; + args.pitches[i] = alignments.at(i).second; + args.modifier[i] = modifier.value_or(0); + } + ioctl::perform(this->m_fd, DRM_IOCTL_MODE_ADDFB2, args); + + this->m_handle = args.fb_id; +} + +void Framebuffer::destruct() noexcept { + if (this->m_fd < 0) { + return; + } + + drm_mode_fb_cmd2 args{ + .fb_id = this->m_handle + }; + try { + ioctl::perform(this->m_fd, DRM_IOCTL_MODE_CLOSEFB, args); + } catch (...) { + assert(false && "Framebuffer close failed, memory leak likely"); + } + + this->m_fd = -1; +} |
