9#include <config-kwin.h>
14#include <drm_fourcc.h>
23static inline std::optional<DmaBufAttributes> dmaBufAttributesForBo(gbm_bo *bo)
25 DmaBufAttributes attributes;
26 attributes.planeCount = gbm_bo_get_plane_count(bo);
27 attributes.width = gbm_bo_get_width(bo);
28 attributes.height = gbm_bo_get_height(bo);
29 attributes.format = gbm_bo_get_format(bo);
30 attributes.modifier = gbm_bo_get_modifier(bo);
32#if HAVE_GBM_BO_GET_FD_FOR_PLANE
33 for (
int i = 0; i < attributes.planeCount; ++i) {
34 attributes.fd[i] = FileDescriptor{gbm_bo_get_fd_for_plane(bo, i)};
35 if (!attributes.fd[i].isValid()) {
36 qWarning() <<
"gbm_bo_get_fd_for_plane() failed:" << strerror(errno);
39 attributes.offset[i] = gbm_bo_get_offset(bo, i);
40 attributes.pitch[i] = gbm_bo_get_stride_for_plane(bo, i);
43 if (attributes.planeCount > 1) {
47 attributes.fd[0] = FileDescriptor{gbm_bo_get_fd(bo)};
48 if (!attributes.fd[0].isValid()) {
49 qWarning() <<
"gbm_bo_get_fd() failed:" << strerror(errno);
52 attributes.offset[0] = gbm_bo_get_offset(bo, 0);
53 attributes.pitch[0] = gbm_bo_get_stride_for_plane(bo, 0);
67 Map map(MapFlags flags)
override;
68 void unmap()
override;
70 QSize
size()
const override;
76 void *m_mapPtr =
nullptr;
77 void *m_mapData =
nullptr;
79 uint32_t m_mapStride = 0;
82 bool m_hasAlphaChannel;
93 Map map(MapFlags flags)
override;
94 void unmap()
override;
96 QSize
size()
const override;
103 void *m_data =
nullptr;
106 bool m_hasAlphaChannel;
110 : m_gbmDevice(device)
120 if (!
options.modifiers.isEmpty()) {
124 drm_mode_create_dumb createArgs{
125 .height = uint32_t(
options.size.height()),
126 .width = uint32_t(
options.size.width()),
129 if (
drmIoctl(gbm_device_get_fd(device), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) {
130 qCWarning(KWIN_CORE) <<
"DRM_IOCTL_MODE_CREATE_DUMB failed:" << strerror(errno);
135 if (drmPrimeHandleToFD(gbm_device_get_fd(device), createArgs.handle, DRM_CLOEXEC, &primeFd) != 0) {
136 qCWarning(KWIN_CORE) <<
"drmPrimeHandleToFD() failed:" << strerror(errno);
137 drm_mode_destroy_dumb destroyArgs{
138 .handle = createArgs.handle,
140 drmIoctl(gbm_device_get_fd(device), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
144 return new DumbGraphicsBuffer(gbm_device_get_fd(device), createArgs.handle, DmaBufAttributes{
146 .width = options.size.width(),
147 .height = options.size.height(),
148 .format = options.format,
149 .modifier = DRM_FORMAT_MOD_LINEAR,
150 .fd = {FileDescriptor(primeFd), FileDescriptor{}, FileDescriptor{}, FileDescriptor{}},
151 .offset = {0, 0, 0, 0},
152 .pitch = {createArgs.pitch, 0, 0, 0},
156static GraphicsBuffer *allocateDmaBuf(gbm_device *device,
const GraphicsBufferOptions &options)
158 if (!
options.modifiers.isEmpty() && !(
options.modifiers.size() == 1 &&
options.modifiers.first() == DRM_FORMAT_MOD_INVALID)) {
159 gbm_bo *bo = gbm_bo_create_with_modifiers(device,
166 std::optional<DmaBufAttributes> attributes = dmaBufAttributesForBo(bo);
167 if (!attributes.has_value()) {
171 return new GbmGraphicsBuffer(std::move(attributes.value()), bo);
175 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
176 if (
options.modifiers.size() == 1 &&
options.modifiers.first() == DRM_FORMAT_MOD_LINEAR) {
177 flags |= GBM_BO_USE_LINEAR;
178 }
else if (!
options.modifiers.isEmpty() && !
options.modifiers.contains(DRM_FORMAT_MOD_INVALID)) {
182 gbm_bo *bo = gbm_bo_create(device,
188 std::optional<DmaBufAttributes> attributes = dmaBufAttributesForBo(bo);
189 if (!attributes.has_value()) {
193 if (flags & GBM_BO_USE_LINEAR) {
194 attributes->modifier = DRM_FORMAT_MOD_LINEAR;
196 attributes->modifier = DRM_FORMAT_MOD_INVALID;
198 return new GbmGraphicsBuffer(std::move(attributes.value()), bo);
207 return allocateDumb(m_gbmDevice,
options);
210 return allocateDmaBuf(m_gbmDevice,
options);
215 , m_dmabufAttributes(std::move(attributes))
216 , m_size(m_dmabufAttributes.width, m_dmabufAttributes.height)
217 , m_hasAlphaChannel(alphaChannelFromDrmFormat(m_dmabufAttributes.
format))
224 gbm_bo_destroy(m_bo);
234 return m_hasAlphaChannel;
239 return &m_dmabufAttributes;
247 access |= GBM_BO_TRANSFER_READ;
250 access |= GBM_BO_TRANSFER_WRITE;
252 m_mapPtr = gbm_bo_map(m_bo, 0, 0, m_dmabufAttributes.
width, m_dmabufAttributes.
height, access, &m_mapStride, &m_mapData);
256 .stride = m_mapStride,
263 gbm_bo_unmap(m_bo, m_mapData);
272 , m_size(attributes.pitch[0] * attributes.height)
273 , m_dmabufAttributes(std::move(attributes))
274 , m_hasAlphaChannel(alphaChannelFromDrmFormat(m_dmabufAttributes.
format))
282 drm_mode_destroy_dumb destroyArgs{
285 drmIoctl(m_drmFd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
290 return QSize(m_dmabufAttributes.
width, m_dmabufAttributes.
height);
295 return m_hasAlphaChannel;
300 return &m_dmabufAttributes;
306 drm_mode_map_dumb mapArgs{
309 if (
drmIoctl(m_drmFd, DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) {
310 qCWarning(KWIN_CORE) <<
"DRM_IOCTL_MODE_MAP_DUMB failed:" << strerror(errno);
314 void *address = mmap(
nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_drmFd, mapArgs.offset);
315 if (address == MAP_FAILED) {
316 qCWarning(KWIN_CORE) <<
"mmap() failed:" << strerror(errno);
324 .stride = m_dmabufAttributes.
pitch[0],
331 munmap(m_data, m_size);
338#include "gbmgraphicsbufferallocator.moc"
339#include "moc_gbmgraphicsbufferallocator.cpp"
QSize size() const override
~DumbGraphicsBuffer() override
Map map(MapFlags flags) override
DumbGraphicsBuffer(int drmFd, uint32_t handle, DmaBufAttributes attributes)
const DmaBufAttributes * dmabufAttributes() const override
bool hasAlphaChannel() const override
GbmGraphicsBufferAllocator(gbm_device *device)
~GbmGraphicsBufferAllocator() override
QSize size() const override
const DmaBufAttributes * dmabufAttributes() const override
GbmGraphicsBuffer(DmaBufAttributes attributes, gbm_bo *handle)
bool hasAlphaChannel() const override
Map map(MapFlags flags) override
~GbmGraphicsBuffer() override
int drmIoctl(int fd, unsigned long request, void *arg)
std::array< uint32_t, 4 > pitch