/* SPDX-License-Identifier: MIT */ #include "drm++/mode/framebuffer.hpp" #include "drm++/gem.hpp" #include "drm++/helper/ioctl.hpp" #include "drm++/helper/types.hpp" #include #include #include #include #include #include #include #include using namespace drm; using namespace drm::mode; Framebuffer::Framebuffer( int fd, u32 width, u32 height, u32 format, std::vector> planes, std::vector> alignments, std::optional 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; }