summaryrefslogtreecommitdiff
path: root/src/mode/framebuffer.cpp
diff options
context:
space:
mode:
authorPancakeTAS <pancake@mgnet.work>2026-07-03 16:15:45 +0200
committerPancakeTAS <pancake@mgnet.work>2026-07-03 16:30:05 +0200
commit5dea03465384a91466c293e55deabd0817c7e0bd (patch)
tree7e884acb1bba09fc86487f76ea06e7e1c22781cc /src/mode/framebuffer.cpp
parentImplement version ioctl and expand comments (diff)
Implement framebuffer object
Diffstat (limited to 'src/mode/framebuffer.cpp')
-rw-r--r--src/mode/framebuffer.cpp70
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;
+}