1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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;
}
|